Guild icon
swift-developers-japan
main / swift
Avatar
omochimetaru 3/21/2017 2:16 AM
こっちにも貼っとくか
2:16 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
これは僕もfileprivate導入しっくり来てなかったです( ´・‿・`) (edited)
2:17 AM
ファイルスコープのprivate概念自体は好きです
Avatar
omochimetaru 3/21/2017 2:17 AM
「fileprivate廃止してswift2仕様に戻そうぜ」
Avatar
The private keyword should be reverted back to its Swift 2 file-based meaning and the fileprivate keyword should be deprecated.
これ派ですね
2:20 AM
こんなすぐ戻そう議論が出てくるくらいのものを https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md でどうして採用に至ってしまったのかなと不思議です🤔 メーリス漁れば分かりそうですが
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 3/21/2017 2:21 AM
そこらへんの空気感は謎ですね
🤔 1
2:22 AM
自分自身は、微妙な気はしつつも、SE25のレビュープロセスの時に当事者意識は無いので何も言えんけど (edited)
2:25 AM
@mono ここって招待自由ですか?
Avatar
@omochimetaru 自由です、アクセス権など弄って無いですが、それもじゃんじゃん付与してしまってよいかな気分です( ´・‿・`) でも、作って放置状態なので、ちゃんと話したい場合、 https://ios-developers-ja.slack.com の方がオススメだと思いますが( ´・‿・`)
Avatar
omochimetaru 3/21/2017 2:27 AM
@mono あれ、こんなのもあるの・・・
Avatar
omochimetaru 3/21/2017 2:28 AM
ほんとだ
Avatar
omochimetaru 3/21/2017 2:38 AM
あつまった
🎉 2
2:40 AM
@hiragram さっきの件だけど、メソッド足すだけでconformできるのと、フィールドも足さないとできないのは大きな違いがあると思う
Avatar
一番新しいので言うと、cellHeightsを管理するのは誰ぞという。何かしら任意のタイミングで変更しなきゃ使えないじゃん
2:42 AM
アイコン変えたい
Avatar
omochimetaru 3/21/2017 2:42 AM
@tarunon アイコン設定しよ
Avatar
変えた
Avatar
@tarunon willDisplayCellcellHeights を更新して、 estimatedRowHeightAtIndexPath で読み出すからdelegateメソッドでしか使われてないよね、という話ではなく?
2:43 AM
@mono おじゃまします 🙏
Avatar
omochimetaru 3/21/2017 2:45 AM
気持ちはわかる
Avatar
willDisplayCellだとestimatedRowHeightに関与できなくね
2:45 AM
できるの?
2:45 AM
おっと、打ち合せだ、一旦離脱します
Avatar
omochimetaru 3/21/2017 2:46 AM
気持ちはわかるんだけど、なんかそういうの楽にやりたいとかは、ビューとかに限った話で
Avatar
humu
Avatar
omochimetaru 3/21/2017 2:46 AM
ライブラリとかでそういうフィールドが外装されてる可能性があるとしんどい
Avatar
そのしんどみがまだピンときてないんだけど、ライブラリ使用者としてということだよね
Avatar
最近カスタムビュー作るほどではないなってときに Extension でプロパティ持てなくて死んだし、気持ちとしては間違いなくあるもののうーん
Avatar
omochimetaru 3/21/2017 2:47 AM
@biacco42 カスタムビューじゃないのにプロパティもつ意味がぜんぜんわからん
2:48 AM
@biacco42 生のUIViewを改造したいって意味?
2:48 AM
@hiragram そうだね、どこから何が変化してどういう状態遷移するのか、ソースコードだけから追いかけようとした時に
2:48 AM
@hiragram フィールド(StoredProperty)ってのは足場として重要
Avatar
ImageView にドラッグアンドドロップお試しでつけたいなー、お、Extension あるやんけ(死亡) みたいな (edited)
Avatar
あー、状態を持つものがあっちこっちにあるとそもそも読むの辛いよねという話ね
Avatar
omochimetaru 3/21/2017 2:48 AM
@biacco42 なんかそれは逆に継承してカスタムビュー作れば良いだけの話じゃない?
2:49 AM
カスタムビュー作るほどではない
2:49 AM
↑ここが気持ちが弱いだけに見える
2:49 AM
カジュアルにカスタムすればいいだけ
Avatar
気持ちが弱いのはそれはそう
Avatar
omochimetaru 3/21/2017 2:49 AM
あと、もしそれができちゃうと、別の所のImageViewも影響を受けちゃう
Avatar
それは思った
Avatar
omochimetaru 3/21/2017 2:50 AM
@hiragram うんうん
Avatar
読むの辛いはわかるものの、やっぱりextension+stored property欲しいという気持ちはある
Avatar
omochimetaru 3/21/2017 2:52 AM
問題はさ
2:52 AM
そのstored propertyがそのextensionだけからしか使われて無ければ
2:52 AM
いいけど
2:52 AM
そのstored propertyをまた他のところから参照してたりするとカオスになりそう
Avatar
それはわかる
Avatar
omochimetaru 3/21/2017 2:53 AM
@hiragram なので、ViewControllerとかは、あまり読む事大事じゃないと思ってて、1度書くことの重要性が実際高いと思う
2:53 AM
ViewControllerは画面仕様と結合度が高いから再利用する事自体稀だし。
Avatar
やりたいことはスコープというか文脈ごとにextensionを分けてその中のprivateなメソッドとプロパティで全部それぞれが完結して他のextension同士は互いを知らなくていいっていうのがやりたいなあなのでextension内のプロパティをそのスコープ外に公開したいきもちはない
Avatar
omochimetaru 3/21/2017 2:54 AM
それってさ
2:54 AM
そのやりたいことの単位を
Avatar
型に分けろ説はある
Avatar
omochimetaru 3/21/2017 2:54 AM
classかstructにまとめれば
2:54 AM
保証できるのでは?
Avatar
それな
Avatar
omochimetaru 3/21/2017 2:55 AM
で、実装本体は、そのまとめた単位を並べるコードと
2:55 AM
メソッドをそのまま転送するコードの束にすると
2:55 AM
見通しが良さそうだし再利用性も高そう。
Avatar
やっぱちゃんとやるならそうやって型に分けるべきだよね〜
Avatar
omochimetaru 3/21/2017 2:56 AM
やりたいことをextensionごとにわけて隔離するつもりがあるなら、型切っておけばうっかり相互依存するのも防げるしね
Avatar
でっかいクラスをザクザクextensionに分けまくっていらないプロパティを消しまくるみたいなリファクタを最近やったのでextension好き〜という気持ちが勝手に高まってるだけかもしれない
Avatar
omochimetaru 3/21/2017 2:57 AM
なるほど
2:57 AM
なんか引き継ぎで萎えてたやつかな
Avatar
そう
Avatar
omochimetaru 3/21/2017 3:02 AM
やっぱextensionでフィールド追加は良くないなあと思ってきた
3:02 AM
最近カスタムビュー作るほどではないなってときに Extension でプロパティ持てなくて死んだし、気持ちとしては間違いなくあるもののうーん
3:02 AM
↑これが氾濫しそう
3:03 AM
hirariの言ってる自作クラスの実装の縦割りのためならまだわかるけど
3:03 AM
UIKitに対してそれをやるようになって
3:03 AM
秩序が完全に終わりそう
Avatar
カスタムビュー作るほどではない
プロダクトコードなら殴りそう
3:04 AM
まーTextKitの系がヒラギノでレンダリング終わってて一括で変えたいとかはあるんだけど
Avatar
前述の通りプロトタイピングでお試し実装したかったときなのでさすがにプロダクションには載せないですね…
Avatar
omochimetaru 3/21/2017 3:04 AM
OtameshiImageView一個作っておけばok
💪 1
Avatar
UIKitに対してそれをやるようになって秩序が完全に終わりそう
それは起きそうなので出来なくていいので https://twitter.com/hiragram/status/844008993932505089 class HogeObj { } が書いてあるファイルでのみHogeObjのextensionにstored propertyを持たせられるようになったらな〜という話。これだったらUIKitのクラスに対してextensionでstored property足せない
大元の定義と同じファイル内だったらextension内でstored property使えるようにしてくれよ
Avatar
omochimetaru 3/21/2017 3:11 AM
なるほど。
Avatar
自作クラスの実装の縦割りのためならまだわかるけど
コレだけができれば僕ははっぴー
Avatar
omochimetaru 3/21/2017 3:11 AM
class本文の中で // MARK: -- で分けるのはどうかと思ったけど、 protocol conformanceが一番上に集まっちゃうから微妙かな (edited)
Avatar
結局みんなどうしてるのか気になる
Avatar
「このプロパティはこの範囲でしか使われない」ということを明示したくて、且つその範囲をなるだけ狭くしたいので、それだと達成できないかなー
Avatar
omochimetaru 3/21/2017 3:13 AM
やはりそれは別classだなという感じがしてくるw
3:13 AM
機能要件としては完全にそう
3:14 AM
他の言語だと、「あるprotocolへのconformanceは、フィールドでもってるこのオブジェクトに全部転送する」ことを1行で記述できたりするんで
Avatar
それが欲しいな
Avatar
omochimetaru 3/21/2017 3:14 AM
そういうのがあるとクラスで分けた時に、転送メソッドを書き下す手間が無くて良さそうじゃないか
Avatar
@omochimetaru それきになる 他の言語ってたとえばどれですか
Avatar
omochimetaru 3/21/2017 3:15 AM
ちょっとまってね
Avatar
omochimetaru 3/21/2017 3:23 AM
Rustで見た気がしたけど提案にすぎなかった
3:23 AM
Sorry if something similar has already been proposed. In short A nice feature of usual OO languages is the implicit code reuse through inheritance: the fact a subclass does not need to redeclare any method existing in its base class provided the behaviour is the one expected. Wouldn't it be a nice feature if Rust had some syntaxic sugar to mimic this ? Composition and inheritance When I have: // java-like language interface Foo { void doSomething(); } class Bar : Foo { void do...
3:23 AM
委譲 (delegation) とはオブジェクト指向プログラミングにおいて、あるオブジェクトの操作を一部他のオブジェクトに代替させる手法のこと。
3:23 AM
Go[編集] Go言語においては、他の言語と異なり始めから委譲を想定した委譲専用構文を備えている。
(edited)
3:24 AM
Goもそれっぽい機能があったけどなんか詳細が、コレじゃない感
Avatar
Goか
Avatar
omochimetaru 3/21/2017 3:25 AM
rubyのこれも近いけど、言語自体にinterfaceが無いせいでメソッド全部並べてるな・・・
3:26 AM
Kotlin is a statically typed programming language for the JVM, Android and the browser, 100% interoperable with Java
3:26 AM
あった!
3:26 AM
kotlinだ!
3:26 AM
interface Base { fun print() } class Derived(b: Base) : Base by b
3:27 AM
bはこれ、型名のところに書いてるけどコンストラクタ引数とフィールド定義を同時にやってるので、 bBase 型のフィールドで、 DerivedBase に conformさせるのを by b で指定してる。
3:28 AM
The by-clause in the supertype list for Derived indicates that b will be stored internally in objects of Derived and the compiler will generate all the methods of Base that forward to b.
Avatar
"Baseに準拠したbをもってDerivedもBaseに適合したことにする" ということよね
Avatar
omochimetaru 3/21/2017 3:29 AM
そうです〜
Avatar
これは良い
Avatar
omochimetaru 3/21/2017 3:29 AM
これが class の右にしか書けないけど、 Swiftなら conformanceがそもそもextensionに書けるわけだから
3:30 AM
extension UserStatusViewController : UIScrollViewDelegate by scrollViewDelegateMixIn {}
3:30 AM
みたいに書けたらイイネ
Avatar
おー
Avatar
omochimetaru 3/21/2017 3:31 AM
scrollViewDelegateMixInUserStatusViewController の storedProperty名で struct ScrollViewDelegateMixIn : UIScrollViewDelegate という型がついてる想定。 (edited)
3:31 AM
あーまあフィールドは class { } の中に書かないといけないならkotlinみたいに上のところでもいいのかな
Avatar
今でもscrollViewDelegateの実装をクラスに切り出すことは出来るはずで(VCがGenericsなら3.1以降で)
6:36 AM
extension ViewController { class ScrollViewDelegate: UIScrollViewDelegate { //ここに実装 } } だけどこれでも、ViewController.ScrollViewDelegateの宣言は本体側にないといけないよね、そこは解決しないのでは。まあすっきりはするか。
Avatar
omochimetaru 3/21/2017 6:42 AM
@tarunon うん、ここで話してたのは、クラスを切っても結局デリゲートメソッドを転送するだけのメソッドを全部書かないといけないのがめんどいね、という問題がのこるので、そこの糖衣構文がほしいねという事
Avatar
別にViewController.ScrollViewDelegateをDelegateにセットする、でも現状大きな問題ない気がするけどな
Avatar
それおもった
Avatar
だけど、糖衣構文が有ろうと無かろうと、var scrollViewDelegate: ScrollViewDelegateをどこに書くの?と言う問題は残っている
Avatar
omochimetaru 3/21/2017 6:47 AM
@tarunon ああ〜 tableView.delegate = self の右辺が self じゃなくてもいいじゃんって事か
Avatar
そう
Avatar
omochimetaru 3/21/2017 6:47 AM
すっかり忘れてたけどそれは確かにありだね
Avatar
class ScrollViewDelegate: NSObject, UIScrollViewDelegate { weak var parent: ViewController? } とかでまあおおよそ問題はないはず
Avatar
omochimetaru 3/21/2017 6:48 AM
var を書くのは本体class {} 部分でいいじゃんと思ってるけどね〜
Avatar
それでいいなら現状そういう作り方すれば問題はなくなる
6:49 AM
どこに入れるかは趣味がありそうだけどね
Avatar
omochimetaru 3/21/2017 6:49 AM
まあ、それで解決するのはScrollViewみたいな .delegate = なケースだけで (edited)
6:49 AM
一般のprotocol conformanceの話では成り立たないけど
Avatar
そうね
Avatar
omochimetaru 3/21/2017 6:51 AM
あれ、Discordって
6:51 AM
syntaxハイライトあるのか。
💯 1
Avatar
適当にmarkdown書いたら普通に動いてびっくりしてる
Avatar
omochimetaru 3/21/2017 6:52 AM
Slackに対する優位性だ
6:57 AM
let a = 3
6:57 AM
let a = 3
6:57 AM
おお〜〜〜
6:57 AM
言語指定構文も使えるやんけ
Avatar
めっちゃいいじゃんこれ
Avatar
# 見出し
6:57 AM
コードブロックだけか
Avatar
omochimetaru 3/21/2017 6:58 AM
  • aaa
6:58 AM
strong1 strong2 (edited)
Avatar
  • や _ による強調はできたけど
Avatar
引用もさっき使った感じなかった気がする
Avatar
箇条書きやリンクはできなかった
Avatar
引用だめなのか
Avatar
custom emojiはないんですか
Avatar
omochimetaru 3/21/2017 6:59 AM
@hiragram あるよ
Avatar
あ、リンクってのは Swift みたいなの。
Avatar
あるのか
Avatar
omochimetaru 3/21/2017 6:59 AM
僕が入ってる身内の鯖で変な絵文字流行ってる
Avatar
シンタックスハイライトはいいなぁ。できれば箇条書きもほしいけど。
Avatar
omochimetaru 3/21/2017 6:59 AM
- aaa - bbb
6:59 AM
なるほど
Avatar
@omochimetaru なんでコードフェンスの中に箇条書き書いてるの??
Avatar
omochimetaru 3/21/2017 7:01 AM
@koher なんかこの中がすごい構文なのかなって試した
7:01 AM
画面共有機能を含む「Discord」のアップデート予告が公開 https://t.co/YpgCv5yPkh
7:01 AM
画面共有できるようになるならSkypeのユースケース消えるわ
Avatar
引用は結構使うから > で引用できないのはちょっと微妙だなぁ。
Avatar
omochimetaru 3/21/2017 7:03 AM
@koher 引用や箇条書きは > や - のままでも見た目にわかるし平気な気もする
Avatar
@omochimetaru まあ、たしかに Slack みたいに >> の二段目だけ > になっちゃうよりマシかも?
Avatar
omochimetaru 3/21/2017 7:04 AM
2段目問題なんてあったのかw
Avatar
とりあえず > とか - で書いておいて Discord のアップデートに期待とか
👍 2
9:22 AM
@koher との合作でコメント投稿した
9:23 AM
class C { p: number; // Should be an error under --strictNullChecks method() { this.p; } }
💯 1
Avatar
やっぱ GitHub だと見やすいね。 Swift の ML も早く移行してほしい。
Avatar
omochimetaru 3/22/2017 9:23 AM
Swiftユーザー各位には信じられないと思うがTypeScriptが提供する --strictNullChecks は このようなコンストラクタでのフィールドの初期化忘れに対して何も検査しないため 簡単に undefined を踏むのだ (edited)
Avatar
Githubに移行して治安維持出来るのか気になるマン
Avatar
omochimetaru 3/22/2017 9:27 AM
GithubじゃなくてDiscorseという掲示板?サービスよ
9:28 AM
治安は悪くなるけどそれこそこういう事は減るんじゃないかな・・・ https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
www
9:29 AM
「俺達は雰囲気でfileprivateとprivateを使い分けている」
9:29 AM
って割りとありそう
Avatar
今日まさに、 private プロパティに(同じファイル中の) extension からアクセスしようとして残念な気持ちになった。
9:30 AM
private let な定数をそっと ViewController の外に出した・・・
Avatar
omochimetaru 3/22/2017 9:30 AM
外w
Avatar
private struct Hoge {} fileprivate struct Hoge {} これが一番モニョい
Avatar
omochimetaru 3/22/2017 9:31 AM
@tarunon 別に定義できんの?
Avatar
いや違う
9:31 AM
両者が(多分)同じ
9:31 AM
ああ、中身が外から見れなくなる違いはあるか?
Avatar
確かにトップレベル private 書く時、意味が fileprivate なので微妙な気持ちになる。private func とか。
Avatar
omochimetaru 3/22/2017 9:32 AM
あ、そうなのか。なるほど。
9:32 AM
トップレベルにおけるprivateはスコープがファイル、みたいな雰囲気か
9:33 AM
クラスの中とかだとprivateがそのクラス自身でfileprivateだと外側のファイルレベルまで広がると
Avatar
そのクラス自身
そのスコープ。同じファイルでも extension の中からはアクセスできない
Avatar
omochimetaru 3/22/2017 9:34 AM
extensionはクラスの外ってイメージでした。
9:36 AM
SwiftMLのフォーラム引越しのスレ見て
9:36 AM
スレッド別れまくってて「いいね!」みたいなレスがついてるだけだったりして
9:36 AM
やはりMLは無理ではという気持ちになる
9:37 AM
「引越しプランは追って出すけど忙しいからとりあえず方向性だけアナウンスしたよ」 って感じのようですね
Avatar
今日まさに、 private プロパティに(同じファイル中の) extension からアクセスしようとして残念な気持ちになった。
昨日まさに同じことになってた
Avatar
omochimetaru 3/23/2017 2:21 AM
class Cat { var a: String { didSet { // 呼ばれない print("nyaa") } } init() { self.a = "a" } } Cat() @here 知ってた?
Avatar
知ってる
Avatar
omochimetaru 3/23/2017 2:21 AM
おー
Avatar
最初にdidSet呼ばれない、はーーー
2:21 AM
ってやった
Avatar
omochimetaru 3/23/2017 2:21 AM
今ためしてて気づいてた。
Avatar
didSetはselfのメンバにアクセスできるから
Avatar
omochimetaru 3/23/2017 2:22 AM
そう!
Avatar
initより前に使えると破綻する
Avatar
omochimetaru 3/23/2017 2:22 AM
そのあたりの挙動を探ってて俺の推測も同じ結論。
2:23 AM
ワンチャンswiftも本物のヌルポが出せるのかと思ったが残念。
Avatar
omochimetaru 3/23/2017 4:38 AM
調べたけどよくわからなくなった
4:39 AM
https://gist.github.com/omochi/90326839d097cc162c0d7e30d5f5e9bb IUOの暗黙キャストについて調べた結果。メソッド呼び出しは T? へのキャストはされない事がわかった。 TT? 両方行けるときは T? になることがわかった。
Avatar
まあ妥当だと思う
4:39 AM
だけど遅そう
Avatar
omochimetaru 3/23/2017 4:39 AM
https://gist.github.com/omochi/ea49fb9cae8b1073c6cedfa1661b697c 元々のコンパイル時間の増大について調べた結果。要素が1つ増えると、コンパイル時間が4倍に増える。
4:41 AM
両方通る場合は T? になることから、 T では駄目になる事を検証しているという仮説は成り立たなかった。 TT? の倍々で増えていくという仮説についても、 4倍で増えていくことから成り立たなかった。
Avatar
うーん
4:45 AM
4:45 AM
これを見る限りはTとT?があり得る場合にTを優先しているようにも見えるんだが
Avatar
omochimetaru 3/23/2017 4:46 AM
ちゃう、それは俺の検証見るとわかるけど、そもそもメソッド呼び出しの時は T? への暗黙キャストはしない。
4:46 AM
.hoge() ってドット構文になった時点で Int しか試されない。
Avatar
ふむ
Avatar
omochimetaru 3/23/2017 4:47 AM
両方を試すのは関数が引数IntとInt?でオーバロードされてるときだった。
Avatar
func commonIntFunc(_ x: Int?) -> Int {...} func commonIntFunc(_ x: Int!) -> Int {...} この2つは共存出来ないのか
Avatar
omochimetaru 3/23/2017 4:49 AM
マジか
Avatar
IntとInt!は共存できるので
4:50 AM
引数としてはInt?の扱いに近い
Avatar
omochimetaru 3/23/2017 4:50 AM
ほんとだ〜〜
Avatar
この検証だと
4:51 AM
引数の時に特別扱いされることが考慮されていないので
4:51 AM
Int?が優先される証左にはならない気がする
Avatar
omochimetaru 3/23/2017 4:51 AM
うーんでも、純粋な検証はそもそもできないよ
Avatar
まあそらなw
Avatar
omochimetaru 3/23/2017 4:51 AM
常に何かしらの場合に依存した検証になってしまう。 (edited)
4:52 AM
さっきのはコンストラクタ呼び出しだったから
4:52 AM
コンストラクタ呼び出しと関数呼び出しで挙動が違う可能性は否定できないから
4:52 AM
まあコンストラクタも試してみたほうがいいかも。
Avatar
コンストラクタも同じっぽいね
4:53 AM
でもこれ
4:54 AM
TとT?をオーバーロードしてる時にどっちを優先するか、と
4:54 AM
T!からT?へキャストをするときの性質がどうなのか
4:54 AM
は、完全に別の問題な気がしていて
4:54 AM
この検証は面白い結果だけど
Avatar
ww
Avatar
omochimetaru 3/23/2017 7:59 AM
16個を試すと退勤時刻が来る・・・
Avatar
どんなmacでやってるのん
Avatar
omochimetaru 3/23/2017 7:59 AM
@hiragram ひらりのやつは引数が2個だったけど、シンプルに1個にして調べたよ
Avatar
okok
Avatar
omochimetaru 3/23/2017 8:00 AM
MacBook (Retina, 12-inch, Early 2015)
Avatar
ちっさいやつか
Avatar
omochimetaru 3/23/2017 8:00 AM
1.3 GHz Intel Core M
Avatar
つらすぎる
Avatar
omochimetaru 3/23/2017 8:00 AM
機種名: MacBook 機種ID: MacBook8,1 プロセッサ名: Intel Core M プロセッサ速度: 1.3 GHz プロセッサの個数: 1 コアの総数: 2 二次キャッシュ(コア単位): 256 KB 三次キャッシュ: 4 MB メモリ: 8 GB
Avatar
引数
引数2個で、5KのiMacで配列が6個のとき15秒なんだけど、引数1と2でこんなに違うんね
Avatar
omochimetaru 3/23/2017 8:01 AM
多分引数2個で要素6個は引数1個で12要素と同じだから
8:02 AM
で、僕のだと12個のとき33秒だから
8:02 AM
そっちが15秒なら2倍ぐらいの速度が出てるってことかな?
8:02 AM
多分並列化が効かないタスクで単純に周波数のスピードになってる
Avatar
2x6ってことか
Avatar
omochimetaru 3/23/2017 8:03 AM
3GHz x 4core ぐらいじゃない?
Avatar
↑機種名のやつってどこでみれるの
Avatar
omochimetaru 3/23/2017 8:03 AM
で、単純に単一コアでの3GHz : 1.3GHzの比率
8:03 AM
左上のりんごのアイコンから
8:03 AM
このmacについて → システムレポート
Avatar
機種名: iMac 機種 ID: iMac17,1 プロセッサ名: Intel Core i7 プロセッサ速度: 4 GHz プロセッサの個数: 1 コアの総数: 4 二次キャッシュ(コア単位): 256 KB 三次キャッシュ: 8 MB メモリ: 32 GB
Avatar
omochimetaru 3/23/2017 8:04 AM
4G!
8:04 AM
つっよ
Avatar
会社のだよ
Avatar
omochimetaru 3/23/2017 8:04 AM
うん。
Avatar
Speeeはアプリエンジニアこれだよ
Avatar
omochimetaru 3/23/2017 8:04 AM
おー
8:04 AM
俺のも会社費用だけど、個人的な希望で軽い方がいいから
8:04 AM
スペックは下げてる。
8:05 AM
MBP15inchの人が多いね。
Avatar
いま1個席が空いて1台余ってるのでスピ社どうぞ
Avatar
うちはMBP15inchすな
8:05 AM
ww
Avatar
omochimetaru 3/23/2017 8:05 AM
ここでリクルートするなw
Avatar
MBP Touch bar だけど、外付けキーボードないと発狂するよ
Avatar
omochimetaru 3/23/2017 8:05 AM
hiraraiためしに俺のgistのコードそのまんまで12個にしてやってみると何秒か教えて欲しい
Avatar
ok
Avatar
omochimetaru 3/23/2017 8:06 AM
俺は計測は time コマンドの real を張ってる。1回しかやってないし他の作業も止めてないからだいぶガバガバだけど。 (edited)
Avatar
~ (๑˃̵ᴗ˂̵)ﻭ < time swiftc compile.swift -o compile swiftc compile.swift -o compile 15.78s user 0.30s system 99% cpu 16.137 total
8:07 AM
33秒と比べると半分くらいか
Avatar
omochimetaru 3/23/2017 8:08 AM
引数2個x要素6個のときの12秒って結果とほぼおなじってことか。
Avatar
ぽい
8:12 AM
プロンプトが可愛いということに誰も触れてくれなくてかなしい
Avatar
omochimetaru 3/23/2017 8:13 AM
あ、それシェルに出てるのかw
Avatar
omochimetaru 3/23/2017 8:14 AM
いつ青い顔に変わるの?
Avatar
exit 0以外のとき
Avatar
omochimetaru 3/23/2017 8:14 AM
ステータスか
8:14 AM
へ〜
Avatar
Ctrl+Cしてもなる
Avatar
omochimetaru 3/23/2017 8:14 AM
Ctrl+Cはシグナル送るからだいたいそうなるね
Avatar
そそ
8:15 AM
コレ自体はどっかzshの設定といっしょに拾ってきた受け売りなんだけどね
8:15 AM
かわいいからきにいってる
Avatar
omochimetaru 3/23/2017 8:15 AM
なるほど
8:15 AM
かわいいけど飽きそう
Avatar
かなしい
Avatar
可愛いシェルより可愛いコード
8:21 AM
はやくして、やくめでしょ
Avatar
可愛いコードとは
Avatar
IUOでコンパイルタイム4^nは良いおやつだった
Avatar
おやつw
Avatar
fileprivateネタ手厚く載ってました( ´・‿・`) https://swiftweekly.github.io/issue-62/
This week swift-stdlib-tool was open-sourced, a number of proposals were accepted, Swift releases have themes, and a new proposal for fixing access controls in Swift is now under review!
Avatar
omochimetaru 3/24/2017 1:39 AM
TypeScriptの初期化をSwiftのように型安全にしようとして議論に参加している件だけど、 そもそもTSからコンパイルした先のJS ES2016のクラス機能の仕様が厳しくて、厳しくなってきた 厳しさ1. super()を呼び出した後でしか this が使えないためサブクラスのフィールドを埋める前に親クラスのコンストラクタが呼ばれる 厳しさ2. サブクラスのコンストラクタ内部で呼ばれた親クラスのコンストラクタにおいてメソッドを呼び出すと、それがサブクラスでオーバーライドされている場合、サブクラスの実装が呼ばれる これらの組み合わせによって、フィールドが未初期化のサブクラスのメソッドが呼ばれて、 undefined を踏む。 下記はその問題によって、純粋なJSユーザーが困っている事例2件 http://stackoverflow.com/questions/32615034/call-parent-function-which-is-being-overridden-by-child-during-constructor-chain http://stackoverflow.com/questions/32449880/parent-constructor-call-overriden-functions-before-all-child-constructors-are-fi
I've encounter a problem below with JavaScript(ES6) class A{ constructor(){ this.foo(); } foo(){ console.log("foo in A is called"); } } class B extends A{ constructor(){ sup...
ECMAScript 6 (Harmony) introduces classes with ability to inherit one from another. Suppose I have a game and some basic class to describe basic things for bot behavior. I simplify my real architec...
Avatar
omochimetaru 3/24/2017 2:02 AM
@mono 最後に乗ってるMatthewのコメントが不穏ですねw ファイルスコープになった private と、構文スコープになった scoped に再び分裂する、みたいな流れになったら草
Avatar
ww
Avatar
omochimetaru 3/24/2017 2:02 AM
たしかに機能が悪いんじゃなくてキーワードの名前が悪いって気はする。
Avatar
fileprivateと打つのは怠いですね
Avatar
omochimetaru 3/24/2017 2:03 AM
自然と手が伸びる方は private ですよねえ。
2:04 AM
お、 @ikesyo さんも来た (edited)
🤗 2
Avatar
omochimetaru 3/24/2017 2:43 AM
@here ここにKotlinのletメソッドについて知ってる人居ますか?Swiftに同じものを実装する事ができないんですけど、 @koher が演算子にしたらどう?って言っていて、わりと良さそうな気がしている。
2:45 AM
kotlinのletは・・・ https://github.com/JetBrains/kotlin/blob/1.1.0/libraries/stdlib/src/kotlin/util/Standard.kt#L62 /** * Calls the specified function [block] with `this` value as its argument and returns its result. */ @kotlin.internal.InlineOnly public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
kotlin - The Kotlin Programming Language
2:46 AM
Rubyのtapとおそらく等価 http://ref.xaio.jp/ruby/classes/object/tap
2:47 AM
仮にこれを => 演算子でSwiftに導入すると、次のような事ができる
2:51 AM
// こんな関数があったとして func hogehogeFunc(str: String, int: Int) -> String { return "" } // こんなStructがあったとして struct Cat { var name: String var age: Int } // こんな関数が合ったとして func createPrettyCat() -> Cat { return Cat(name: "mike", age: 2) } // 従来は・・・ func demo1() { let cat = createPrettyCat() let result = hogehogeFunc(str: cat.name, int: cat.age) print(result) } // こういうのがシュッと1行にできなくて萎える // 提案のもとでは・・・ func demo2() { print(createPrettyCat() => { hogehogeFunc(str: $0.name, int: $0.age) }) } // 左から右にシュ〜っとかける
Avatar
Contribute to swiflet development by creating an account on GitHub.
2:53 AM
説明してる間に実装しちゃった。
2:53 AM
=> の方がいい?
Avatar
omochimetaru 3/24/2017 2:53 AM
@koher ホタルイカみたいな演算子 ->> より ダブルアローのほうが 打ちやすくていい
Avatar
任意の構造をモナドと見做してmapしたい感じですかね
Avatar
omochimetaru 3/24/2017 2:54 AM
モナドとは違うよ、 => 式の評価結果はクロージャの結果そのものだから、
Avatar
ですよねこれつよい
Avatar
omochimetaru 3/24/2017 2:54 AM
モナドに包まれる必要はない。
2:55 AM
ただ指摘の通り使い勝手はモナドに近い。
Avatar
確かに箱は存在してない
Avatar
=> にするか。
Avatar
Rubyのtapはレシーバ自身を返すので型変換はなく、等価じゃないですね
Avatar
omochimetaru 3/24/2017 2:55 AM
@ikesyo あ〜・・・そうですね
2:55 AM
あれ? tapの末尾に評価値かけなかったっけ
Avatar
hoge => { $0.piyo } => { $0.fuga }
Avatar
omochimetaru 3/24/2017 2:55 AM
@Biacco42 yes
2:55 AM
you can
Avatar
すごーい!たーのしー! (edited)
Avatar
omochimetaru 3/24/2017 2:56 AM
任意のテンポラリ値を変数に束縛できるので 左から右に書けない時に、だいたいそれができるようになります
2:56 AM
わざわざ let で変数におかなくちゃ〜〜 みたいな気持ちの時に効く
Avatar
Rename した
2:58 AM
前から @omochimetaru との間で Kotlin の let が Swift にほしい話があって、でも Any に extension でメソッド生やせないから諦めてた。
2:58 AM
で、さっきまたほしくなって、よく考えたら演算子だったらいいんじゃない?って思った。
2:58 AM
関数だと順序が気に入らないけど、演算子だと let メソッドと同じ順序で書ける。
Avatar
omochimetaru 3/24/2017 2:59 AM
それで、そうやってすぐ演算子に逃げるの良くないよと思ったんだけど、でも、Swiftでは何にでもあるメソッドって作れないから、実際メソッドとは違う特別な存在なんだよな、と思って。 (edited)
3:00 AM
class Cat attr_accessor :name, :age def initialize @name = "mike" @age = 3 end end p Cat.new.tap {|x| x.age } # => #<Cat:0x007f1790eb9b60 @name="mike", @age=3> Rubyのtapは確かに違った。。 (edited)
Avatar
SwiftPM に対応してるので、↓だけで使えます。 dependencies: [ .Package(url: "https://github.com/koher/swiflet.git", majorVersion: 0) ] (edited)
👏 1
Avatar
Objective-Cの時にまさにtapを作っていたのを思い出した https://github.com/ikesyo/NSObject-Tap
NSObject-Tap - tap: method for Objective-C borrowed from Ruby.
Avatar
omochimetaru 3/24/2017 3:40 AM
@ikesyo 本当だ〜
Avatar
この間のT! -> T?変換が遅い件、何も別にIUOをswitchしなくても
9:34 AM
func fastUnwrap<T>(_ arg: T!) -> T? { return arg } (edited)
9:34 AM
これだけでいい気がしてきた
9:37 AM
いけたっぽい
Avatar
それは暗黙の変換にはならないんですか
Avatar
暗黙の変換が return arg として出現していますが
Avatar
探すわけじゃないからいいのかな
Avatar
こいつはfuncで1回しか評価されないため
10:44 AM
差し当たりO(4)かな?
10:44 AM
fastUnwrapの方は別段問題が発生しない。明示的だから。
Avatar
ふむ
Avatar
omochimetaru 3/28/2017 2:09 AM
Swift3.1のGeneric Classのinner classって
2:09 AM
外側のGeneric Classの型パラメータによって
2:09 AM
static contextって分離されるの?
2:09 AM
つまり・・・
2:10 AM
class Outer<T> { static var staticVar: T class Inner { static var staticVar: T } }
2:10 AM
としたとき
2:10 AM
Outer<Int>.staticVar = 3 Outer<String>.staticVar = "abc" Outer<Int>.Inner.staticVar = 4 Outer<String>.Inner.staticVar = "xyz"
2:10 AM
こう?なんだっけ?
Avatar
そもそもstatic なT作れたっけ
Avatar
omochimetaru 3/28/2017 2:11 AM
えーっと、そもそものstaticなTについては、Swift3.0でも問題になるテーマだから、どうだろう。
2:12 AM
Innerがあってもそれを一貫して引き継いだ仕様になるか。
Avatar
そうだと思うよ
Avatar
omochimetaru 3/28/2017 2:12 AM
なんかアプデがエラーになっちゃってまだ試せていない・・・
Avatar
iPadで試そう
Avatar
omochimetaru 3/28/2017 2:12 AM
Swift Playgroundsは3.1なんだよねw
Avatar
omochimetaru 3/28/2017 2:30 AM
なんかAppStoreアプリぶっ壊れてXcodeのアプデが終わらん
Avatar
devから直接ダウンロードすればいいんでない?
Avatar
staticなTは無理みたいですね error: static stored properties not supported in generic types static var staticVar: T
Avatar
まあそうですよね (edited)
Avatar
omochimetaru 3/28/2017 2:56 AM
なるほど
2:56 AM
じゃあ CatInt, CatString は static contextが2つあるけど、 Cat<Int>, Cat<String> は1つしか無いんだな
Avatar
static var x = 0を生やして書き換えたら共有されるのかな?
Avatar
@tarunon
Tは暗黙的にT?だよ
古い話題ですが、これ、メソッドコールだと起こんないんですよね。 let a = 42 a.map { $0 } // error
(edited)
Avatar
そうですね、その場合はOptionalは決定しようがなさそう
Avatar
このあたりは使い勝手を考えると絶妙なラインだけど、法則がわかりづらすぎてやっぱり暗黙の型変換は邪悪・・・
3:09 AM
昔 Kotlin の Any?map を生やしてみたら、 Listmap が正しく動かなくなって大変なことに。
Avatar
ListがList?に変換されたのか
Avatar
はい。
Avatar
邪悪だ
Avatar
それで初めて、 Swift の T? への暗黙の型変換は起こる場合と起こらない場合が使い分けられていることに気付きました。
Avatar
swiftの場合は、他の要素によってOptionalが決定される場合にのみ暗黙的に変換されるので、辛うじて秩序を保てている(?)
3:11 AM
🤔
Avatar
正確なルールがどうなってるのかはわからないです。単に . の左側では暗黙の型変換をしないだけかもですが。
Avatar
.の左って暗黙変換すると非決定性が高すぎて実現不可能な気がするんですが
3:26 AM
他の言語で例があったりするのかな
3:26 AM
ObjCのidがある意味そうか。でもあれはobjc_msgSendだからswiftの話とは全然違う (edited)
Avatar
C++とかどうなってるんでしょう?
3:27 AM
暗黙の型変換ができる言語自体が少ない気も?
Avatar
vtableか何か、implを引ける仕組みがあれば、そこに乗せればいい気はしてるんですが
3:31 AM
そういうのが無い場合に出来るイメージが全く湧かない
3:31 AM
いや、左の型が非決定的だからvtableあっても意味ない
Avatar
Java のオートボクシングでできそうな気がしたけどできなかった。 public class Main { public static void main(String[] args) { System.out.println(2.compareTo(3)); } } $ javac Main.java Main.java:3: error: ')' expected System.out.println(2.compareTo(3)); ^ Main.java:3: error: not a statement System.out.println(2.compareTo(3)); ^ Main.java:3: error: ';' expected System.out.println(2.compareTo(3)); ^ 3 errors
Avatar
ObjCも本質的に違う話題ですね、あれはOオブジェクトとselectorからimpl引いてるだけだ
Avatar
↓なら OK 。 aint に変えたらダメ。 public class Main { public static void main(String[] args) { Integer a = 2; System.out.println(a.compareTo(3)); } }
Avatar
omochimetaru 3/28/2017 3:34 AM
C++の暗黙の型変換は引数に渡す時だけな気がする
3:34 AM
ドットオペレータでメソッドを呼ぶ時は差し込まれない
Avatar
単純にやっぱり、型を決定する材料足りないと思う
Avatar
omochimetaru 3/28/2017 3:34 AM
static var x = 0を生やして書き換えたら共有されるのかな?
そうそう。そこらへんが気になった。
(edited)
Avatar
KotolinのAny?の話は聞いた感じ
3:35 AM
😳😥😰って感じ
Avatar
まあ、基本的に nullable にメソッドは生えてないので、意図的に生やさなければ問題にはならないです。 (edited)
Avatar
map flatMapないのか
Avatar
let みたいな Any 由来のメソッドは使えるけど、それは暗黙の型変換なく使えるんで。
Avatar
そうか、kotlinはT??とT?が等価でしたっけ
Avatar
はい
Avatar
なるほど
Avatar
foo?.let { x -> bar(x) }
3:39 AM
↑が map かつ flatMap になります。
Avatar
なるほどー
3:40 AM
まあ実用上75%くらいは問題ないですね
Avatar
です。
Avatar
omochimetaru 3/28/2017 3:40 AM
?.let { } はアツいよね
Avatar
↑に気づく前の Kotlin を使い始めたばかりの頃に map を生やしてみたら、という話なので、実用上は問題ないです。
Avatar
Promise.thenみを感じる
Avatar
Kotlin と言えば、この前 @omochimetaru と話してた Ceylon : Anything : Null = Kotlin : Any? : Nothing? の話を整理して Qiita に書きたい。 (edited)
3:44 AM
typealias Anything = Any? typealias Null = Nothing? とすれば Ceylon と同じになる。
3:45 AM
typealias Object = Any これもいるか。
3:46 AM
で、これと関連して、 Swift の Never が bottom type になるかもという話も興味深い。
3:48 AM
Joe Groff の言ってる↓がもし実現されるなら https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170213/032267.html IMO, if we accept a single error type per function, there could be a simpler model for this. We could say that the `throws` type is a generic parameter of all function types, and it defaults to the uninhabited `Never` type for functions that don't throw. () -> () == () throws Never -> () () throws -> () == () throws Error -> () In this model, you'd get many benefits: - `rethrows` could become first-class, reducing down to just polymorphic `throws`: func foo(_: () throws -> ()) rethrows // Swift 3 func foo<T: Error>(_: () throws T -> ()) throws T // Swift X
3:48 AM
Never が bottom type でないと辻褄が合わない。
Avatar
ああ、そういう意味か
3:49 AM
いいですね、美しい
Avatar
これはこれでキレイなんですけど、 rethorws がただのシュガーになっちゃって、 reasync との対応の解釈が難しいです・・・。 https://gist.github.com/koher/df007741788cb197d65b6babe2acf480
Avatar
asyncの話は出てないんですか?
Avatar
ちゃんと watch できてないです・・・。
3:53 AM
でも Swift 4 のスコープじゃなさそうな気も?
3:54 AM
Generics と Memory Ownership と String でお腹いっぱいなんじゃないですかね。
Avatar
それはそんな気がする
3:55 AM
asyncも後から足して破壊的変更になるか、というと
3:55 AM
stdlib周りが壊れるかー
Avatar
壊れますか?追加だけなような気も。
Avatar
ああ、追加すれば良いのか
3:56 AM
殺さなくて良いので確かに
Avatar
↓の Chris Lattner のスライドの actor も Swift 5+ って書かれてるし、 4 ではない気がしてます。 http://researcher.watson.ibm.com/researcher/files/us-lmandel/lattner.pdf
3:58 AM
多分、 async レベルの変更は Core Team で良く練った上でマニフェストが出て、それベースで話し合いとかじゃないですかね?
7:11 AM
public class func Package(url: String, versions: ClosedRange<Version>) -> Dependency { return Package(url: url, versions: versions.lowerBound..<versions.upperBound.successor()) }
7:12 AM
a...ba..<b の両方に対応しようとすると、 a...b => a ..< b.successor() の変換をオーバーロードの内側でやらないといかんのか。
Avatar
あーーー
7:22 AM
Swift3.1でコンパイルできなくなった
Avatar
omochimetaru 3/28/2017 7:22 AM
w
Avatar
Swift2.2になって、Protocol周りのバグが幾つか修正されて、ProtocolとClassを組み合わせて使うシチュエーションが現実的になってきました。 ということで、Swift2.2から可能になったテクニックを備忘録も兼ねて...
7:25 AM
これ、extensionの束縛部分を他のライブラリに逃してたら今まで通ってたけど
7:25 AM
ついに殺されたっぽい
7:26 AM
エラーの出方もAmbiguous type nameじゃなくてセグフォだしとても嫌な感じだ…
Avatar
omochimetaru 3/28/2017 7:28 AM
たるのんのこれ、いまいちシナリオがわからなかったけど
7:28 AM
ここでいう recursive protocol constraints に該当するパターンかね
Avatar
それそれー
Avatar
omochimetaru 3/28/2017 7:28 AM
protocol Sequence { associatedtype Iterator : IteratorProtocol ... associatedtype SubSequence : Sequence // currently ill-formed, but should be possible } シーケンスのサブシーケンスはシーケンス、としたいけど現状はできない、とかがあるらしい
Avatar
今まではWorkaround作って無理やり押し通ってた
7:29 AM
しんでしまった
7:29 AM
どうしようかな~
Avatar
omochimetaru 3/28/2017 7:30 AM
あ〜
7:30 AM
protocol Eq { static func (a: Self, b: Self) -> Bool } ↑これはできるけど protocol EqX { associatedtype X static func (a: X, b: X) -> Bool } struct Hoge : EqX { typealias X = Hoge } これはできない? (edited)
Avatar
nn
7:31 AM
↑は↓の糖衣では
Avatar
omochimetaru 3/28/2017 7:31 AM
2つめのはできて、 protocol EqX { associatedtype X static func (a: X, b: X) -> Bool } protocol EqSelf { typealias X = Self } struct Hoge : EqSelf { } これが駄目なのかな?
Avatar
Equatableは暗黙的にassociatedだぞ
7:32 AM
えっとですね
Avatar
omochimetaru 3/28/2017 7:32 AM
記事で本題ってなってるケースは↑のEqXも駄目になりそう。
7:32 AM
protocol EqX { associatedtype X static func (a: X, b: X) -> Bool } struct Hoge : EqX { typealias X = Self } HogeじゃなくてSelfか (edited)
Avatar
protocol A { associatedtype B } class C: A { typealias B=Self } ↑できない
Avatar
omochimetaru 3/28/2017 7:33 AM
だよね
Avatar
サブクラスのBはサブクラス自身であってほしいが、それが出来ない
7:33 AM
しかし、Workaround積み上げまくってそれを実現してた
7:33 AM
バベルの塔はついに崩壊した
Avatar
omochimetaru 3/28/2017 7:33 AM
Cを継承したDがいるときに
7:34 AM
Cの中でSelfって書いておくとDにおいてそれがDになるやつよね
Avatar
そうそう
Avatar
omochimetaru 3/28/2017 7:34 AM
そもそもSelfって書けるの最近しったワw
7:34 AM
しかも self 式の型が Self だし。
7:35 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
7:35 AM
RecursiveProtocolConstraintsはAcceptedになってるし
Avatar
4までおあずけかな
Avatar
omochimetaru 3/28/2017 7:36 AM
待ってれば綺麗な解決が来そう
Avatar
@tarunon これだとまた意味変わってきます? protocol HasB { associatedtype B } protocol A: HasB { } class AnyAs: HasB { typealias B = AnyAs.Type } class AnyA<T>: AnyAs where T: A { typealias B = T.B } class C: A { typealias B = C } AnyA<C>.B.self
Avatar
class D: C {}と書いたらどうなりますか?
10:05 AM
昔は、AnyAとか用意しなくても、常にA.B==Selfな型が作れたんですが、今は死んでしまったので。
Avatar
確かに継承してしまうと追いかけてくれないですね...うーむ
Avatar
なんかObjCと絡ませて型をしっちゃかめっちゃかするとコンパイル通らなくなるなー最小ケース探さないと
Avatar
omochimetaru 3/29/2017 1:30 AM
Swiftに慣れてくるとRubyのコードがこんなんばっかになる xs.map {|x| y = f(x) y ? [y] : [] }.flatten(1)
Avatar
みつけた
5:05 AM
セグフォです
Avatar
いけそうだけどダメなんですね 💧 fugaのみだと通るのか...
Avatar
Xが具体型なら通ります、この場合はStringに変更すればOK
Avatar
なるほど
Avatar
Swift3.1 ErrorからNSErrorへの暗黙の型変換追加されてるくさい
7:23 AM
邪悪すぎる
Avatar
omochimetaru 3/29/2017 7:23 AM
それ前からあったと思う
Avatar
いや
Avatar
omochimetaru 3/29/2017 7:23 AM
全てのError は is NSError だった
Avatar
error.method
7:23 AM
これでerrorがNSErrorになる
Avatar
w
Avatar
omochimetaru 3/29/2017 7:23 AM
あーそゆこと?まじ?
Avatar
多分
7:24 AM
もうちょっと掘るけど、かなり辛い感じ
7:29 AM
理解完了
7:29 AM
7:29 AM
こういうコードを書いた時に、前までだと
7:29 AM
キャストが先だったが3.1からNSErrorへのキャストが先に挿入されてから変換される
Avatar
NSErrorが優先されるのか
7:30 AM
あ、順番の話か
Avatar
omochimetaru 3/29/2017 7:30 AM
MyCustomErrorのhogeとNSErrorのhogeの値を変えて欲しい
Avatar
変えてる
Avatar
1と-1
Avatar
1と-1
Avatar
omochimetaru 3/29/2017 7:30 AM
あ、見間違えた
7:30 AM
ほんとだ・・・
Avatar
let error: Error 👉 error as NSError 👉 (error as NSError) as? MyCustomErrorProtocol ということ? (edited)
Avatar
そう
7:32 AM
強制的にNSErrorになってる
Avatar
21行目を let error: MyCustomError = MyCustomError() にしたらどうなるの?
7:32 AM
それは1か
Avatar
そう
7:32 AM
でもthrowがErrorだから型明記するの全く意味ない
Avatar
おー
7:33 AM
extension NSError: MyCustomErrorProtocol これ消せばちゃんと動くんよね
Avatar
それはそう
Avatar
へー
7:35 AM
参考までにこの変更で何が困ってるのか聞いてもいいですか
Avatar
Errorを受け取ってダイアログ出してるけど
7:36 AM
3.1にしたら全てが破壊されて???ってなった
7:36 AM
ダイアログはProtocolに基づいてラベル付をしている。
Avatar
カテゴリ分けみたいな意図でprotocolを使っていてってことかな
Avatar
error.method これでerrorがNSErrorになる
タイムリーに昨日話してた . の左の暗黙の型変換ですかw
Avatar
ほぼ
8:01 AM
それですね
8:01 AM
激怒ですよ
8:03 AM
なんか
8:03 AM
そのくせNSErrorの引数にError渡したらコンパイルエラー吐きやがったぞ…
8:03 AM
ふざけやがって…
Avatar
そっちは暗黙の型変換ないんですね。カオスw
Avatar
迂闊にNSErrorにprotocol準拠させて共通化するの危険になりましたね... 修正するならNSError用のcontainerで包むとか別で対応入れる形になるんでしょうか
Avatar
コンテナ作ってError型入れて
8:52 AM
Protocolでキャストして片方取り出しつつ、NSErrorの処理はそこに書く
8:53 AM
みたいなことしなきゃいけないです。あーめんどくせーーー
Avatar
やっぱりそうなりますよね。。NSErrorの存在感w
Avatar
protocolでキャストする必要が出てくるのでAssociatedなProtocolは死体ですねこれ
9:26 AM
無念
Avatar
全然関係ない話ですが、
9:35 AM
Swift PM の新しい pinning について、
Since package pin information is not inherited across dependencies, our recommendation is that packages which are primarily intended to be consumed by other developers either disable automatic pinning or put the Package.pins file into .gitignore, so that users are not confused why they get different versions of dependencies that are those being used by the library authors while they develop.
https://github.com/apple/swift-evolution/blob/master/proposals/0145-package-manager-version-pinning.md とあるんですが、これについて話していて pins ファイルは ignore しない方がいいんじゃないかという話になったんですがどう思いますか? アプリでは環境をそろえるために pins ファイルを共有した方がいいのは当然として、ライブラリ利用時には、依存している側からはライブラリ内部の pins ファイルは無視されるようなので、 "so that users are not confused why they get different versions of dependencies that are those being used by the library authors while they develop." という理由だけであればライブラリ開発者間で環境をそろえるために( atuo pinning も有効にして) pins ファイルも push した方がいいんじゃないかなぁという話です。
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 3/29/2017 9:38 AM
ライブラリ開発中は依存先のバージョンが
9:38 AM
微妙に変わったりした時に
9:38 AM
壊れる事を検出したいから
9:38 AM
固定しないほうがたまに壊れてくれて嬉しい気がする
9:38 AM
もし、特定のあるバージョンでしか、動かないライブラリなら
9:39 AM
pinじゃなくて、そもそものPakcage.Swiftのほうで、ピンポイント依存していをしないと
Avatar
それは明示的に repin して確認すればいい話なのでは?
Avatar
omochimetaru 3/29/2017 9:39 AM
いけないのではないか
9:39 AM
めんどくさくてやらなそう>明示的に
9:39 AM
とりあえず固定しないでおけば、いろんな人が作業するタイミングのズレで自然とバラける
Avatar
アプリにせよライブラリにせよ、それぞれが微妙にブレたバージョンで開発していたりすると微妙なバージョンのブレの組み合わせが原因で問題が起こったりして現象を再現できないから
9:41 AM
開発者間でバージョンをそろえて作業できるようにしたいというニーズがそもそもあって pinning が導入されたと思っていて
9:41 AM
色んなバージョンで動くかどうかの検証はそれとは別の話じゃないかな。 pinning してなくても網羅的にチェックできるわけじゃないし。
Avatar
cocoapods使っててPodfile.lockをignoreするかしないか論争のSwift PM版って話ですよね チームで開発してるときなんかはそれぞれで環境が変わると問題が起きたときに切り分けに困るのでpinsは共有した方が良い派です (edited)
Avatar
@moaible ですよねぇ・・・。
9:44 AM
ignore するか auto pinning を disable することが推奨って書いてあるんですけど、それによって得られるメリットが "users are not confused why they get different versions of dependencies that are those being used by the library authors while they develop" なのは納得がいかないんですよね・・・。
9:45 AM
@omochimetaru
めんどくさくてやらなそう
デフォルトが auto pinning になるから、もし pins ファイルを commit しないなら、少なくとも auto pinning を disable するか、 pins ファイルを ignore するかしないといけないんです。
Avatar
omochimetaru 3/29/2017 9:46 AM
--type libraryで初期化してもauto piningがデフォルトでoffになってない?
9:46 AM
それはよくわからないな。
9:47 AM
一貫性が無い
Avatar
The package manager will have automatic pinning enabled by default (this is equivalent to swift package pin --enable-autopin), although package project owners can choose to disable this if they wish to have more fine grained control over their pinning behavior.
(edited)
Avatar
omochimetaru 3/29/2017 9:48 AM
ウーム
Avatar
アプリ作る人はpinsを含めたほうがいいけど、ライブラリ作る人はpinsはignoreしたほうがいいってことじゃないんですかね。
Avatar
@rb-de0 そういう内容なんですが、それが微妙じゃないかなぁという話ですね。
9:59 AM
pins ファイルを commit することのデメリットが「まぎらわしいから」くらいなら、 commit するメリットが勝る気が。
10:00 AM
それに、ライブラリ開発環境の pins が含まれていれば、それを再現すれば最低限そのときと同じ環境でライブラリを動かすことができるわけで、利用者視点でも、トラブル発生時のドキュメントとしても価値があると思うんですよね。
Avatar
Swift2 -> 3のタイミングでのSwift PMは大分辛かった記憶があるのでpinsあるとその辺緩和されると嬉しいお気持ちはありますね
👍 1
10:03 AM
どこで依存壊れてんのか追うのがしんどかったです
Avatar
あんま詳しくないですが、ここに書いてあることと同じ意味なんじゃないですかね。http://sanemat.github.io/archives/langturn.com-translations-33/
Avatar
同じっぽい。rubyやnodejsの開発者のほうが
10:05 AM
ライブラリ小分けにしまくって依存が100個とかぶら下がるみたいな
10:05 AM
開発になれていて
10:05 AM
知見がありそう
Avatar
利用者側からすると依存関係のバージョンがズレていると使えないことになってしまって不便です。
Ruby 詳しくないですが、↑これって利用者側がライブラリ中の lock ファイルの影響を受けるってことですよね?
10:10 AM
Swift PM ではそれは起こらないのでは?
The pins file will also not influence dependency resolution for dependent packages; for example if application A depends on library B which in turn depends on library C, then package resolution for application A will use the manifest of library B to learn of the dependency on library C, but ignore any Package.pins file belonging to library B when deciding which version of library C to use.
Avatar
Gemって依存先のLockも見ちゃうのかな?その文章はどっちでも取れると思いますが
10:13 AM
Gemコマンドで扱われないような精密さを要求してしまうからです。
技術的にって意味じゃなくて、固定して開発するからコードがそうなっちゃうって意味かと思った。
2:49 PM
associatedtypeにデフォルト型置けるようになってる
Avatar
omochimetaru 3/29/2017 2:49 PM
話し合われてるのは知ってたけど3.1からだったか
Avatar
この間のwhere Voidの変態workaroundは用済みとなった
Avatar
omochimetaru 3/29/2017 2:51 PM
あれ謎だった
Avatar
LazyCollectionProtocolとか、その辺見て気が付いた
2:52 PM
あれ?associatedtypeでSelf??マジ?って
Avatar
omochimetaru 3/29/2017 2:52 PM
ふむふむ
Avatar
associcatedtypeのやつって2.xの時からできてたと思ったけど、何か違うものです? https://github.com/ikesyo/Himotoki/blob/1.7.0/Sources/Decodable.swift
Himotoki - A type-safe JSON decoding library purely written in Swift
Avatar
これforceじゃないですかね
2:57 PM
上書き不可能な気がする
2:57 PM
associatedtypeのそれは、他の型で上書きできます
2:58 PM
無宣言の時だけ=の向こう側になる
Avatar
これと同じに見える http://stackoverflow.com/a/36810484
I have been struggling very hard with Swift Protocols and Associated Types for a long time. I started again with basic to really understand what is going wrong and I followed this article of TypeEr...
3:02 PM
手元で今シュっと試せないのでハッキリとは分からないですが(>_<)
Avatar
iswift.orgで試したら3.0.2の時点で出来てたみたいですね
3:04 PM
2.2はSelfが消せなくてコンパイルエラー
Avatar
なるほど3.0でか
3:04 PM
ありがとうございます
3:07 PM
Gemfile/.lockはPodfile/.lockと同じで、それに依存する側からは関係ないはずという認識です。そのライブラリの利用者に影響を与えるのはgemspec, podspecでは?
Avatar
omochimetaru 3/29/2017 3:10 PM
であれば、条件設定はspmとgemで同じですね
3:11 PM
条件設定と、慣習が同じで、 ライブラリ開発時はロックをコミットするな、 で
3:11 PM
でもライブラリ開発同士でも環境が同期したほうが良いのでは?という話
Avatar
CarthageでもCartfile.resolvedはライブラリ利用者には影響を与えない
3:12 PM
Carthageではドキュメントでreslovedはコミットをすすめてるかな (edited)
Avatar
omochimetaru 3/29/2017 3:12 PM
ほー!
Avatar
あ、ですよね
Avatar
開発者間で同期すべきものという認識で、僕もその立場です
Avatar
そんな気はしてた
Avatar
omochimetaru 3/29/2017 3:16 PM
so that users are not confused why they get different versions of dependencies that are those being used by the library authors while they develop.
3:16 PM
実際これはよくわからないよなあ
Avatar
ロックするのはまさにこういうことかなぁ
それに、ライブラリ開発環境の pins が含まれていれば、それを再現すれば最低限そのときと同じ環境でライブラリを動かすことができるわけで、利用者視点でも、トラブル発生時のドキュメントとしても価値があると思うんですよね。
Avatar
omochimetaru 3/29/2017 3:17 PM
ライブラリ作者と違う依存先バージョンを取得していまう理由にユーザーが混乱しないから、と、言われても、依存の依存はLockを見ない、で説明終わるからなあ
3:19 PM
あ~
3:19 PM
CIをまわしている場合に
3:20 PM
CI botもpinしたバージョンでライブラリをビルドするけど
3:20 PM
pinよりも先のリビジョンアップデートがリリースされている場合に
3:20 PM
ライブラリ作者が明示的にupdateしてpinを更新しないと
3:20 PM
それが検査されない、みたいな違いはある?
3:20 PM
ライブラリのロックがコミットされていなければ、
3:21 PM
pushされるたびに依存先のバージョンの指定の範囲で最新のものが使われるから
3:21 PM
健全性は保ちやすい?
3:25 PM
@tarunon どこかで見たつもりだったけどこれしか見つからなかった rejectされた別の提案の一部として出てきてる https://github.com/apple/swift-evolution/blob/9cf2685293108ea3efcbebb7ee6a8618b83d4a90/proposals/0108-remove-assoctype-inference.md#default-type-for-associated-type
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
3:26 PM
うーんどこから入ったんだろう
Avatar
IBMのサンドボックスでは3.0.0時点から可能だった
3:27 PM
見落としてたのかーという気持ち
Avatar
omochimetaru 3/29/2017 3:27 PM
2からいけた可能性は?
Avatar
2.2はしんだ
Avatar
omochimetaru 3/29/2017 3:29 PM
なるほど・・・俺も釈然としない・・・
Avatar
コンパイラはAbortかなこれは
3:29 PM
ああ、まってね
3:30 PM
2.2にprotocol extensionって無かったよね
3:31 PM
いけたいけた
3:31 PM
2.2でも同様の型の作り方書いて上書きできた
Avatar
omochimetaru 3/29/2017 3:31 PM
えーじゃあ全然前からできたってこと?
Avatar
ぽい
Avatar
omochimetaru 3/29/2017 3:32 PM
あれ~~~🙄
Avatar
2.2だとprotocol extension無いからやるメリットはほぼない
3:32 PM
3.0からメリットの塊だけど、見逃し続けてた。今の今まで
Avatar
omochimetaru 3/29/2017 3:32 PM
Himotoki - A type-safe JSON decoding library purely written in Swift
3:32 PM
himotokiのこれも上書き可能ってことかね
Avatar
できちゃいますね
Avatar
omochimetaru 3/29/2017 3:33 PM
oh・・・
Avatar
でもHimotokiはそこら中でwhere Decodable==Selfって書いてた気がする
Avatar
omochimetaru 3/29/2017 3:33 PM
typealiasっていうキーワードの印象で上書きできないって思い込んでただけかな
Avatar
3.0からなんで出来ないと思い込んでたのかが謎
3:34 PM
HimotokiのDecodable==Selfはサブクラスをやっつけてるのかと勝手に解釈してた
Avatar
omochimetaru 3/29/2017 3:36 PM
あいや、それはそうなはずで
3:36 PM
# 先に結論 - Swiftのstaticメソッド制約はちょっとしたシンプルな機能に見えるけど便利で深い - Kotlin, TypeScript, Java で同じことをすると冗長で間接的なコードになってしまう - TypeScr...
3:36 PM
ちょうどこの記事書いたときにも確認してる
Avatar
うん、やっつけれるのは確かなんだけど
3:37 PM
それは兎も角Decoded=Intとか勝手にかけるそれらもやっつけ対象だったのは、完全に盲点だった
Avatar
ロックの件、CIも確かに話題としてありそう。CI上で勝手に新しいの使われてぶっ壊れるのも嫌な気もして、好みによりそう (edited)
3:38 PM
あとはブランチ指定かなー
3:39 PM
複数ライブラリを並行に開発してて、開発中のブランチを使いたい時に、ロックがないと用意に壊れる気がする
Avatar
omochimetaru 3/29/2017 3:39 PM
@ikesyo アプリAから見てライブラリBの依存先Cに勝手に新しいのを使われる事自体はそもそも防止できないのでは
3:40 PM
アプリユーザーはBのpinを無視する仕様だから、Bの開発者はCのリビジョンアップデートはそもそも対応を拒否できない
3:41 PM
(根本的に依存先定義をピンポイント指定すれば別だけど)
Avatar
@omochimetaru それはそうですね。そうなってから何か報告があれば直すというスタンスか、ライブラリ側でそういう状況を常に把握できるようにあえてロックしないか、というスタンスの違い
Avatar
omochimetaru 3/29/2017 3:41 PM
ああ、なるほどです。 (edited)
Avatar
まあその辺はsemverの世界観ではそうそう壊れないという期待はあると思う。compatibleなバージョン範囲を指定してる上では。
Avatar
omochimetaru 3/29/2017 3:44 PM
たまにRails触るとだいたいlibv8となんちゃらモンキーが問題起こしてたから、semverの世界に全く信用がおけない・・・
Avatar
依存先が勝手にアップデートされないためには完全バージョン固定するしかないけど、それはそれで依存の依存に新しいバージョン出てるのにそれが使えなくて困ると上位の利用者から文句言われることになりそう。なので~>とかになる (edited)
Avatar
omochimetaru 3/29/2017 3:46 PM
npmとかも一瞬で200個とかライブラリぶっこまれて、こんなん動くわけないやろって気持ちによくなる。でもnodejsはブラウザ向けとかはわりと動くんだよな。
3:46 PM
そうですね
Avatar
jsのライブラリ粒度はすごい世界だ……
Avatar
omochimetaru 3/29/2017 3:49 PM
ですよねww
3:49 PM
ワンファイルどころか10行ぐらいの関数単位のパッケージがザラにある
3:50 PM
browser swiftとか始まったらブラウザ差分吸収の需要からそういう世界になってしまうんだろうか
Avatar
依存先が勝手にアップデートされないためには完全バージョン固定するしかない
これだと、複数のライブラリが同じ別のライブラリの(互換性のある)バージョン違いに固定されちゃってたら、本来解決できるはずなのに解決できなくなっちゃいますよね?
Avatar
omochimetaru 3/30/2017 2:25 AM
それはそれで依存の依存に新しいバージョン出てるのにそれが使えなくて困ると上位の利用者から文句言われることになりそう。なので~>とかになる
2:25 AM
そういう事ですね
Avatar
ああ、「使えなくて困る」というのは、単に新しいのにしたいけどできないから古いの我慢するというだけじゃなく、そもそも不整合が起こって解決不能になるという意味も含んでいるのか。
2:28 AM
ワンファイルどころか10行ぐらいの関数単位のパッケージがザラにある
これ自体は別にいいと思う。むしろ粒度小さくした方がいい派。
2:32 AM
ライブラリのロックがコミットされていなければ、 pushされるたびに依存先のバージョンの指定の範囲で最新のものが使われるから 健全性は保ちやすい?
この目的だと、pinsファイルをignoreするよりも、開発者側がauto pinningをdisableして何もpinしないのが良さそう。ignoreしてる時点で開発者間で環境そろえられないからpinningの意味ない気がするし。
Avatar
omochimetaru 3/30/2017 2:51 AM
そもそも共有しないpinって意味あるんですか?
2:52 AM
pinが無いと自分の手元もどんどん新しくなるのかな
Avatar
Use Cases
Our proposal is designed to satisfy several different use cases for such a behavior:
1. Standardizing team workflows
When collaborating on a package, it can be valuable for team members (and continuous integration) to all know they are using the same exact version of dependencies, to avoid "works for me" situations.
This can be particularly important for certain kinds of open source projects which are actively being cloned by new users, and which want to have some measure of control around exactly which available version of a dependency is selected.
2. Difficult to test packages or dependencies
Complex packages which have dependencies which may be hard to test, or hard to analyze when they break, may choose to maintain careful control over what versions of their upstream dependencies they recommend -- even if conceptually they regularly update those recommendations following the true semantic version specification of the dependency.
3. Dependency locking w.r.t. deployment
When stabilizing a release for deployment, or building a version of a package for deployment, it is important to be able to lock down the exact versions of dependencies in use, so that the resulting product can be exactly recreated later if necessary.
3:23 AM
うーん、 commit しなくてもうれしいケースがあるとすると 2 かな?
3:25 AM
いずれにせよ auto pinning では 2 は実現できないから、 auto pinning が enabled な状態のまま、 pins ファイルを ignore するシナリオがよくわかんないな。
Avatar
omochimetaru 3/30/2017 3:25 AM
なるほど
Avatar
やっと再現できた
11:41 AM
まだ小さく出来たので小さくした。今のが最小かな
Avatar
omochimetaru 3/30/2017 1:58 PM
a
4.67 KB
1:58 PM
ビルド、実行できたよ
1:58 PM
$ cd a $ swift build $ .build/debug/a
Avatar
Avatar
omochimetaru 3/30/2017 1:59 PM
main.swift let a = F<O>() print(a.f())
Avatar
同じファイルだと動く
Avatar
omochimetaru 3/30/2017 1:59 PM
別のファイルだよ
1:59 PM
tarunonのgistをzipでおとしてから
Avatar
マジか
Avatar
omochimetaru 3/30/2017 1:59 PM
swift package initしたから
1:59 PM
全くおなじはず
Avatar
ふーむ
2:02 PM
出来るな
Avatar
omochimetaru 3/30/2017 2:02 PM
Swiftのライブラリの名前って
2:02 PM
Swiftに洒落を効かせたほうがいいんですかね
2:02 PM
たくさんライブラリを使うようになったら
2:02 PM
そういうのいちいちあるとややこしい気がするんだけど
2:03 PM
あーでも同じことをするライブラリが2つあったら微妙なのかな
2:04 PM
でもResultとかあるしな
Avatar
同じコードの二つのプロジェクトがあって
2:29 PM
片方は通って片方はセグフォになった
Avatar
omochimetaru 3/30/2017 2:29 PM
ええw
2:29 PM
ビルドキャッシュの影響じゃない?クリーンしたら同じになるよ
Avatar
いや、
Avatar
omochimetaru 3/30/2017 2:30 PM
import GlibC したとき何が使えるのかさっぱりわからん (edited)
Avatar
消しても再現するし、DerivedData消しても同じ
Avatar
omochimetaru 3/30/2017 2:31 PM
ふむ
2:32 PM
UbuntuならGlibc.swiftmoduleとかあると思うんだけど、あったとして、中身見る方法もわからんな・・・
Avatar
タイミングとしては、extensionに書いたfの解析中にセグフォで死ぬ
2:33 PM
今死んでる方はバグの再現できるプロジェクトから最小単位まで削ったコードで、会社のpcに最初からプロジェクト作って再現したのがあるから、
2:34 PM
明日そのプロジェクトをzipに詰めてアップロードしとこう
2:34 PM
githubに上げるのがはやいか
Avatar
omochimetaru 3/31/2017 1:45 AM
@ikesyo さんとか、HimotokiのLinux対応やったとき、Glibcの中身ってどうやって確認したんでしょうか
1:45 AM
サーバーサイドLinuxでGlibc叩いてる人は居ませんか〜〜
Avatar
HimotokiはstdlibとFoundationだけで済んでいてGlibcは使ってなかったと思います
Avatar
omochimetaru 3/31/2017 2:37 AM
あ〜 じゃあLinux固有のヘッダーを読む必要は無かったんですね
2:37 AM
Mac上でFoundationを外すだけで作業できた
Avatar
FoundationはLinux版でもcorelibs-foundation使ってるので外してはないですけど、Glibcを使う必要はなかったですね (edited)
Avatar
omochimetaru 3/31/2017 2:42 AM
corelibs-foundationってFoundationのLinux対応版の事ですか?
Avatar
https://github.com/apple/swift-corelibs-foundation/ Swift実装のFoundation(≒Linux版)
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
2:44 AM
macOSでもSwiftFoundationとして独立して動きます(なのでmacOSで開発、テストもできる)
Avatar
omochimetaru 3/31/2017 2:44 AM
なるほど
2:44 AM
なるほど〜
Avatar
omochimetaru 3/31/2017 3:12 AM
deferの中でthrowできないのか・・・
Avatar
returnより後ろだから無理じゃないの
Avatar
omochimetaru 3/31/2017 3:16 AM
var fileActions: posix_spawn_file_actions_t? try PosixError.run { posix_spawn_file_actions_init(&fileActions) } defer { try PosixError.run { posix_spawn_file_actions_destroy(&fileActions) } }
3:16 AM
これとかすごい素直なコードだと思うんだけど通らなくて悲しい
Avatar
いやVoid値返ってからエラー発生はおかしいでしょ
3:17 AM
それやったらtryがEitherと等価じゃなくなる
Avatar
omochimetaru 3/31/2017 3:17 AM
返ってからじゃなくてreturnの直前に差し込まれるんじゃないのかね
3:17 AM
コンパイル結果的には。
Avatar
返り値確定してから差し込まれてるから、deferの中にthrowは直感に反するというか
Avatar
omochimetaru 3/31/2017 3:18 AM
いや、てか、defer自体が open - defer { close } ってパターンが基本だと思うんだけど
Avatar
混乱生みそう
Avatar
omochimetaru 3/31/2017 3:18 AM
このcloseが失敗した時が無理じゃない?
3:19 AM
それができないなら、javaの try - catch -finally のfinallyの代替にはならないね 自分でwith resources文作らないといけないか
Avatar
foo() defer { bar() } return baz()foo() let r = baz() bar() return r と等価だと思ってた。
Avatar
omochimetaru 3/31/2017 3:21 AM
そうそう、そういう話しです
Avatar
それはそうなんですが
Avatar
omochimetaru 3/31/2017 3:22 AM
foo() return baz() bar() こう考えると、throwできないわけだ
Avatar
そう、それはthrowは出来ない
Avatar
omochimetaru 3/31/2017 3:22 AM
deferがいったいどこまで遅延するのか return前だと思っていたけど、後だと考えたほうが
3:22 AM
仕様とは合致して解釈できるね
Avatar
直感的に理解しやすいとは思う
Avatar
omochimetaru 3/31/2017 3:23 AM
微妙な仕様だな・・・
Avatar
defertry できないのは↓書いてるときに遭遇して、できてもいいのになぁと思った。 http://qiita.com/koher/items/e4c1d88981291c35d571
Swift には Java の検査例外によく似た仕組みがあります。 swift func foo() throws -> String { ... } // Java のような `throws` 節 ```swift...
Avatar
omochimetaru 3/31/2017 3:23 AM
with文作るのはいいけど、それだとネストが深くなっちゃうんだよな
3:23 AM
モナドにすればいいのか?
Avatar
iPhone版Playgroundめっちゃ欲しい
3:24 AM
こういうのスッと試したい
Avatar
omochimetaru 3/31/2017 3:24 AM
今mac無いの?
Avatar
でんしゃ
Avatar
omochimetaru 3/31/2017 3:24 AM
deinitもthrowできないし、Swiftのdeinitやdeferは全然RAIIパターンに使えねえんだなあ
3:25 AM
あ〜でもopenできたならcloseできない事はありえないし try! で辻褄あうのか
3:25 AM
一周回ってやっぱり何も問題無い気がしてきた
Avatar
iPhoneだと↓かなぁ。 https://swift.sandbox.bluemix.net/
An interactive website that lets you write, execute, and share Swift code in a server environment – on top of Linux!
Avatar
omochimetaru 3/31/2017 3:26 AM
↑このサイト叩くだけのwebviewアプリがあるといいのか
Avatar
ふむ
Avatar
omochimetaru 3/31/2017 3:27 AM
一応スマホ対応されてるんだな
3:27 AM
アプリ化しなくてもこれブックマークしておけば良い気もしてきた。
Avatar
うん。実行するとアニメーションして結果画面にスライドする。
Avatar
omochimetaru 3/31/2017 3:27 AM
一応SPAサイト化されてるなこれ
3:27 AM
えらい
3:28 AM
なんかいろいろおすとすりあがって来たりしてそれっぽい
Avatar
あ〜でもopenできたならcloseできない事はありえないし try! で辻褄あうのか
これよくわかんないんだけど、 close できないことがありえないならそもそも throws である必要ないんじゃ?
Avatar
APIの設計に依存しそう
3:30 AM
賢い作りならcloseできる時だけオブジェクトが存在してる
3:30 AM
メモリオーナーシップの機能は必要っぽい
Avatar
omochimetaru 3/31/2017 3:31 AM
@koher PosixError.runがそもそも public static func run(proc: () -> Int32) throws { let code = proc() guard code == 0 else { throw PosixError(code: code) } } こういうユーティリティだから try! PosixError.run { posix_spawn_file_actions_destroy(&fileActions) } try! になる
3:32 AM
もしそれをつかわないなら (edited)
3:32 AM
let ret = posix_spawn_file_actions_destroy(&fileActions) fatalError(ret == 0, PsoxiError(code: ret).description) (edited)
3:33 AM
っていうコードになるんだけど、これだと、 ret がスコープ汚染しちゃって、同じような処理を他にも書く必要があるから、これは採用できない。
Avatar
お、この前話してた >= の出番だ。
Avatar
omochimetaru 3/31/2017 3:34 AM
いや、えーっと、
3:34 AM
retの再定義が解決したとしても
3:34 AM
まだ冗長で
Avatar
そういや、 >=rethorws にしないといけない気がしてきた。
Avatar
omochimetaru 3/31/2017 3:34 AM
fatalError(ret == 0, PsoxiError(code: ret).description) 0判定、PosixErrorで包む、descriptionを呼び出す、などが冗長
3:35 AM
try! PosixError.run { posix_spawn_file_actions_destroy(&fileActions) } これならそのいずれもなくなっていて、同じことをする上で無駄が無い
Avatar
>=rethrowsじゃないとダメですね
Avatar
ですよね。
Avatar
はやく
3:38 AM
そういえばRxSwiftのどっかにrethrowsにして統合できる関数があったな
3:44 AM
昨日の、クラッシュするプロジェクトをGithubにおいたので
3:44 AM
Contribute to Xcode3_1Crashes development by creating an account on GitHub.
3:44 AM
お手すきの方コンパイルできるか試して頂けると
Avatar
@ukitaka が謎を解いてくれた
3:56 AM
コンパイラに渡すファイルの順番でコンパイルの可否が決まる
Avatar
えーw
Avatar
プロジェクトに寄って結果が違うのもそれ
Avatar
omochimetaru 3/31/2017 3:58 AM
なにそれw
3:58 AM
SPMだとソース回収だから一貫するけどXcodeだと追加順があるからか・・・
Avatar
プロジェクトタブの、CompileSourcesで順番弄ると
3:59 AM
コンパイル通ったり通らなかったりする
3:59 AM
笑う
Avatar
Foundation無しだとString.componentsすら無いのか・・・
Avatar
String.componentsが内部的にNSStringに依存してる?
Avatar
そこはわからんけど
Avatar
extension NSString { open func components(separatedBy separator: String) -> [String] @available(iOS 2.0, *) open func components(separatedBy separator: CharacterSet) -> [String] }
10:58 AM
これしか見つからん
Avatar
ってことはそもそも暗黙のアップキャスト?
Avatar
じゃねーかなー
Avatar
アップですらないな
Avatar
アップキャストではない気がする
10:59 AM
initしてますね
Avatar
暗黙のキャスト!
Avatar
ちょっと悪い事してみるか
10:59 AM
NSStringもSwiftStringも
11:00 AM
実行時はCFStringだからinstrumentsじゃ見分けつかねーんだわ
Avatar
へ~
Avatar
昔は_NSナンチャラStringが沢山居た気がするんだけど
11:01 AM
SwiftでNSString書いても最初からCFStringっぽい
Avatar
いたいたw
11:02 AM
_NSCFConfiguousString とかそんなん
Avatar
そうそれ
11:02 AM
あー
11:02 AM
じゃあObjC経由でswizzlingしてもだめか
11:02 AM
そもそも奴らはコンクリートクラスだからSwizzlingできねえ (edited)
11:02 AM
じゃあcomponentsかな?
11:08 AM
11:08 AM
詠唱完了
11:08 AM
確定ですね
11:08 AM
componentsはNSString由来、その上暗黙キャストが走ってる
11:08 AM
.の!!左側で!!!
Avatar
お〜〜なるほど
11:09 AM
method_exchangeImplementationsうけるな
Avatar
1年以上ぶりぐらいに詠唱したけど指が覚えてた
Avatar
ww
Avatar
一番知りたいのは
11:10 AM
NSStringがinitされてるか…なんだけど
11:10 AM
うーんどうやって調べれるかな
Avatar
initも同じように差し替えられないの?
11:12 AM
あ、initなんたらがたくさんあると捕まえられない可能性があるのか
Avatar
コンクリートクラスだから実体は違って、initは差し替えられなかった記憶がある
11:12 AM
俺の勘違いでなければ
11:14 AM
暗黙キャストというか
11:14 AM
違うな…なんだ…
11:15 AM
@omochimetaru 会社出ちゃった、NSStringにextension生やしてStringから呼べる?
Avatar
TのコンストラクタでUを受けるものは総じて本来的な型キャストで良いと思う
11:18 AM
import Foundation extension NSString { func piyo() -> Int { return 33 } } let a: String = "abc" a.piyo()
11:18 AM
@tarunon いけるね。
Avatar
実行時は同一のCFStringつまり
Avatar
あ〜、内部の実体が同じ場合はinitが呼ばれてない事もありえるね
Avatar
そそ
11:19 AM
てことはー
11:20 AM
Foundationをimportすると、StringがNSStringとして扱われる魔術がかかる
11:20 AM
structですらない
11:20 AM
ってところかな、キャストとは違う
11:21 AM
置き換わってるのはオブジェクトではなく、型自体だ
11:22 AM
いや、CFStringだからstructか
11:22 AM
むむ、わからんくなってきた
11:22 AM
Foundationに何か魔法が書いてそうだな
Avatar
確かどこかで見たことあるんですが、Objective-Cと互換性を持たせるようにimport Foundationで変更がかかるらしいです
Avatar
Stringはstructだからそれが可能ですね
11:24 AM
だがErrorはprotocolだから無理だな
Avatar
Foundationのクラスを優遇して推論してるような雰囲気ありますよね
Avatar
あーこれかなー
11:27 AM
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
11:27 AM
下の方に魔術用の型が存在する
Avatar
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
Avatar
これを見るに実行時に型変換は走ってるはず
11:28 AM
ですです
11:28 AM
一番下にも居ますね
11:29 AM
この辺が揃っていればコンパイラ君が実行時に暗黙的な変換を許してくれる…
Avatar
_SwiftBridgeable が気になる感
Avatar
2.xまでは内緒プロトコルも、取り敢えず名前を当てればコード見つけられたし、動く型を作れたんですが今はどうかな
Avatar
自分で書いたらStringから暗黙変換される型自作できんのか?w
Avatar
やってみて!
11:32 AM
いや、Stringからの暗黙変換は
11:33 AM
_NSBridgableと_CFBridgableだから
11:33 AM
Stringから、は無理かな
11:33 AM
Stringへ、はいけそう
Avatar
_SwiftBrideableとかが見えないっぽい
Avatar
見えなくても実装できる
11:34 AM
気合で!
Avatar
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
Avatar
3.0の時は気合で実装できたけど
11:34 AM
今はもう防がれた?
Avatar
気合とは・・・
Avatar
型名わかってれば、取り敢えず書くと
11:35 AM
2.xなら全てのメソッドが足りないよと怒られて出てきた
11:35 AM
3.0はどうやったんだったかな
11:36 AM
AnyObjectConvertible - Convert your own struct/enum to AnyObject easily.
11:37 AM
こういうのが出来た。今はもうこいつは要らない
Avatar
それって
11:37 AM
public protocol AnyObjectConvertible: _ObjectiveCBridgeable {}
11:38 AM
この_ObjectiveCBridgeableがFoundationをimportすると見えるからできたのでは?
Avatar
うーん、コード補完は効かないし、参照も出来なかった気がするんだけど
11:39 AM
ああ、2.xはprivate/internalが不完全で
11:39 AM
名前を当てれば動いてしまったからかな
Avatar
ww
Avatar
NSErrorは特にそれっぽいコードなさそうですね...
Avatar
いや、あったはず
11:43 AM
_BridgedStoredNSError
11:43 AM
この辺
Avatar
swift - The Swift Programming Language
Avatar
core側もおもろい
Avatar
昨日のNSErrorの件が気になりすぎてて、色々のぞいて見ます
Avatar
omochimetaru 3/31/2017 2:07 PM
// // util.swift // RuString // // Created by omochimetaru on 2017/03/31. // // internal func findSubArray<C: Collection, I>( array: C, index: I, target: C ) -> I? where I == C.Index { var i: C.Index = index while i < array.endIndex { if matchArray(array1: array, index1: i, array2: target, index2: target.startIndex, length: target.distance(from: target.startIndex, to: target.endIndex)) { return i } i = array.index(after: i) } return nil } internal func matchArray<C: Collection, I, D>( array1: C, index1: I, array2: C, index2: I, length: D) -> Bool where I == C.Index, D == C.IndexDistance, C.SubSequence.Iterator.Element : Equatable { if array1.index(index1, offsetBy: length) >= array1.endIndex { return false } if array2.index(index2, offsetBy: length) >= array2.endIndex { return false } let test1 = array1[index1..<array1.index(index1, offsetBy: length)] let test2 = array2[index2..<array2.index(index2, offsetBy: length)] for (x1, x2) in zip(test1, test2) { if x1 != x2 { return false } } return true }
2:07 PM
util.swift:16:46: Cannot convert value of type 'C.Index' to expected argument type '_.Index'
2:07 PM
うーん・・・
2:09 PM
referenceでもIndexがCollectionのassociatedtypeに書いて無くて
2:09 PM
なぞ
Avatar
型パラ2重に定義してないかこれ
Avatar
omochimetaru 3/31/2017 2:18 PM
最初は C.Index って書いてたんだけど
2:18 PM
それでもだめだった
2:19 PM
internal func findSubArray<C: Collection>( array: C, index: C.Index, target: C ) -> C.Index? { var i: C.Index = index while i < array.endIndex { if matchArray(array1: array, index1: i, array2: target, index2: target.startIndex, length: target.distance(from: target.startIndex, to: target.endIndex)) { return i } i = array.index(after: i) } return nil } internal func matchArray<C: Collection>( array1: C, index1: C.Index, array2: C, index2: C.Index, length: C.IndexDistance) -> Bool where C.SubSequence.Iterator.Element : Equatable { if array1.index(index1, offsetBy: length) >= array1.endIndex { return false } if array2.index(index2, offsetBy: length) >= array2.endIndex { return false } let test1 = array1[index1..<array1.index(index1, offsetBy: length)] let test2 = array2[index2..<array2.index(index2, offsetBy: length)] for (x1, x2) in zip(test1, test2) { if x1 != x2 { return false } } return true }
2:23 PM
あ〜〜〜〜いけた
2:23 PM
上の方の関数に where C.SubSequence.Iterator.Element : Equatable を付ける必要があった
Avatar
ああまあそりゃそうやね
Avatar
omochimetaru 3/31/2017 2:24 PM
エラーメッセージにつられてしまった
Avatar
Collectionの定義からIndex消えてるのはなんやろな
Avatar
omochimetaru 3/31/2017 2:24 PM
それ今のところ
2:25 PM
associatedtype Iterator = IndexedIterator<Self>
2:25 PM
この行によって
2:25 PM
IndexedIterator<T> の Tの制約が 間接的にSelfに掛かって
2:25 PM
SelfがIndex持ちになってる仮説を立てた
Avatar
無茶苦茶な
Avatar
omochimetaru 3/31/2017 2:25 PM
GenericClass<T> の Tのところ使って外側に制約かけてるのでは
Avatar
Collection、前はIndexableみたいな型貼り付けてたよね (edited)
2:27 PM
where Elements : _IndexableBase
2:27 PM
ははーん
2:27 PM
わかった
Avatar
omochimetaru 3/31/2017 2:27 PM
そのElementsがIndexedIterator<Elements>でしょ?
Avatar
_IndexableBase
2:27 PM
こいつはinternalなProtocolなので
2:28 PM
それが前提になったProtocolを外から観測すると
2:28 PM
消えて見える
2:28 PM
なので
Avatar
omochimetaru 3/31/2017 2:28 PM
消えて見えるw
2:28 PM
あ〜 _IndexableBaseにIndexが書いてあってCollectionはそれを継承してる?
2:28 PM
そう
Avatar
omochimetaru 3/31/2017 2:28 PM
でもそれだと、Self.Index見えるのがマズイ気が
2:28 PM
可視性汚染や
Avatar
まあそこはバグってことで
2:29 PM
報告したほうがええんやろか
Avatar
omochimetaru 3/31/2017 2:29 PM
public protocol Collection : _Indexable, Sequence {
2:29 PM
この_Indexableか
Avatar
そやね
Avatar
omochimetaru 3/31/2017 2:29 PM
なるほど・・・
2:29 PM
見えるけど見えない型とは。
Avatar
private/internal隠してるけど隠しきれてないな
2:30 PM
これはーーー
Avatar
omochimetaru 3/31/2017 2:30 PM
バグなのか仕様なのかよくわからんな
Avatar
バグでいいと思うけど
2:30 PM
いたずらできそう
Avatar
omochimetaru 3/31/2017 2:30 PM
まあねえ。
2:31 PM
あと
2:31 PM
String.UnicodeScalarView.init() は呼べるのに
2:31 PM
String.UTF8View.init()が呼べなくて
2:32 PM
これもなんなのか迷ってる
Avatar
謎いな
2:32 PM
悪いことしようとしたらPlayground死んだ
Avatar
omochimetaru 3/31/2017 2:33 PM
extension String.UnicodeScalarView : RangeReplaceableCollection { /// Creates an empty view instance. public init()
2:34 PM
extensionで生えてた
2:34 PM
UTF8Viewには無いのはなぜなんだ〜〜
Avatar
なんじゃこりゃ
2:37 PM
Reflection掘ってたらこんなのあった
2:37 PM
/// A type that explicitly supplies its own playground Quick Look. /// /// A Quick Look can be created for an instance of any type by using the /// `PlaygroundQuickLook(reflecting:)` initializer. If you are not satisfied /// with the representation supplied for your type by default, you can make it /// conform to the `CustomPlaygroundQuickLookable` protocol and provide a /// custom `PlaygroundQuickLook` instance. public protocol CustomPlaygroundQuickLookable { /// A custom playground Quick Look for this instance. /// /// If this type has value semantics, the `PlaygroundQuickLook` instance /// should be unaffected by subsequent mutations. public var customPlaygroundQuickLook: PlaygroundQuickLook { get } }
2:37 PM
楽しそう
Avatar
omochimetaru 3/31/2017 2:37 PM
ほ〜〜
2:38 PM
LiveViewはこの前使ったけど
2:38 PM
こっちはあれかな、1行ごとの結果とかを可視化する方
Avatar
そうそう
2:38 PM
Mirror周りもなんか色々悪いことできそうな感じになってる
2:38 PM
/// A type that explicitly supplies its own mirror. /// /// You can create a mirror for any type using the `Mirror(reflect:)` /// initializer, but if you are not satisfied with the mirror supplied for /// your type by default, you can make it conform to `CustomReflectable` and /// return a custom `Mirror` instance. public protocol CustomReflectable { /// The custom mirror for this instance. /// /// If this type has value semantics, the mirror should be unaffected by /// subsequent mutations of the instance. public var customMirror: Mirror { get } } /// A type that explicitly supplies its own mirror, but whose /// descendant classes are not represented in the mirror unless they /// also override `customMirror`. public protocol CustomLeafReflectable : CustomReflectable { }
Avatar
omochimetaru 3/31/2017 2:39 PM
numswチームに共有しとこ
Avatar
ObjectIdentifierっていうAnyからHash取れる構造も見つけた
2:40 PM
やっぱリフレクション最高やで!
2:40 PM
おもちゃ箱や
Avatar
omochimetaru 3/31/2017 2:41 PM
Hashってハッシュ値?それとも辞書のこと?
Avatar
public struct ObjectIdentifier : Hashable {
2:41 PM
Anyからinitできる
2:41 PM
ああ違う
2:41 PM
AnyObjectとAny.Typeだ
Avatar
まあAnyObject行けるなら事実上いけるか
Avatar
omochimetaru 3/31/2017 2:42 PM
同一性の抽象化か
Avatar
でもBoxになるやろうからあんまり使えないかな
Avatar
omochimetaru 3/31/2017 2:42 PM
In Swift, only class instances and metatypes have unique identities. There is no notion of identity for structs, enums, functions, or tuples.
2:42 PM
かいてあるね。
Avatar
だよなー
Avatar
omochimetaru 3/31/2017 2:42 PM
あ〜〜そうか、これが必要なのって
2:43 PM
== じゃなくて === ベースでDictionaryのキーにしたいときに
2:43 PM
[ObjectIdentifier: Hoge] こうすんのか
Avatar
できるね
2:49 PM
しかしCollectionからIndex消えてるのよろしくないな
Avatar
omochimetaru 3/31/2017 2:49 PM
前は見えたよねえ。
Avatar
不可視のtypealias/associatedtypeはどう考えてもやばい
Avatar
omochimetaru 3/31/2017 2:49 PM
splitメソッド、Foundationに合わせてcomponentsの方がいいんだろうか・・・
2:50 PM
なんかstdlibのジェネリクスは前からワケワカメすぎて、ヤバさがよくわからない
Avatar
いや
2:50 PM
Collection参照した時に
2:50 PM
subscript(index:Self.Index)って書いてあって
Avatar
omochimetaru 3/31/2017 2:51 PM
うん
Avatar
前は飛んでいったらIntが見つかるからああまあIntやねって感じ
Avatar
omochimetaru 3/31/2017 2:51 PM
そうなんよね
Avatar
今はそも飛べない
Avatar
omochimetaru 3/31/2017 2:51 PM
あ〜w
2:51 PM
たしかに。
2:51 PM
昔はそこでとべたな確かに。
Avatar
omochimetaru 3/31/2017 3:46 PM
/// Supply the default "slicing" `subscript` for `BidirectionalCollection` /// models that accept the default associated `SubSequence`, /// `BidirectionalSlice<Self>`. extension BidirectionalCollection where Self.SubSequence == BidirectionalSlice<Self>, Self.SubSequence.Index == Self.Index, Self.SubSequence.IndexDistance == Self.IndexDistance, Self.SubSequence.Indices == DefaultBidirectionalIndices<BidirectionalSlice<Self>>, Self.SubSequence.Iterator == IndexingIterator<BidirectionalSlice<Self>>, Self.SubSequence.SubSequence == BidirectionalSlice<Self>, Self.SubSequence._Element == Self._Element, Self.SubSequence.Indices.Index == Self.Index, Self.SubSequence.Indices.IndexDistance == Int, Self.SubSequence.Indices.Iterator == IndexingIterator<DefaultBidirectionalIndices<BidirectionalSlice<Self>>>, Self.SubSequence.Indices.SubSequence == DefaultBidirectionalIndices<BidirectionalSlice<Self>>, Self.SubSequence.Indices._Element == Self.Index, Self.SubSequence.Iterator.Element == Self._Element, Self.SubSequence.SubSequence.Index == Self.Index, Self.SubSequence.SubSequence.Iterator == IndexingIterator<BidirectionalSlice<Self>>, Self.SubSequence.SubSequence.SubSequence == BidirectionalSlice<Self>, Self.SubSequence.SubSequence._Element == Self._Element, Self.SubSequence.Indices.IndexDistance.IntegerLiteralType == Int, Self.SubSequence.Indices.IndexDistance.Stride == Int, Self.SubSequence.Indices.IndexDistance._DisabledRangeIndex == Int._DisabledRangeIndex, Self.SubSequence.Indices.Iterator.Element == Self.Index, Self.SubSequence.SubSequence.Iterator.Element == Self._Element, Self.SubSequence.Indices.IndexDistance.Stride.IntegerLiteralType == Int { public subscript(bounds: Range<Self.Index>) -> BidirectionalSlice<Self> { get } }
3:46 PM
あたまおかC
Avatar
omochimetaru 3/31/2017 6:12 PM
4> for (i, c) in "a\r\nb".characters.enumerated() { 5. print("[\(i)] \(c)") 6. } [0] a [1] [2] b CR + LFは書記素クラスタとして1つに結合するらしい
Avatar
この前のpinファイルと絡むネタです https://www.slideshare.net/mobile/teppeis/do-you-commit-yarnlock
Avatar
omochimetaru 4/1/2017 6:40 AM
読んでみました。20ページの「ユーザーは?」のところがよくわからない
Avatar
先週のString.compontentsの話
Avatar
omochimetaru 4/3/2017 2:34 AM
うん
Avatar
スタック見るの忘れてたからチェックしたら
2:35 AM
一応Stringに生えているみたいだった
Avatar
omochimetaru 4/3/2017 2:35 AM
あ〜
Avatar
libswiftFoundation.dylib`(extension in Foundation):Swift.String.components (separatedBy : Swift.String) -> Swift.Array<Swift.String>:
Avatar
omochimetaru 4/3/2017 2:35 AM
Foundationの中でextensionが生えてるだけか
2:35 AM
じゃあNSStringへの変換はやってないけど中で同じ実装は呼んでる (edited)
Avatar
そうそう
Avatar
omochimetaru 4/3/2017 2:35 AM
なるほど
Avatar
0x1032ae46b <+43>: callq 0x103326aaa ; symbol stub for: Swift.String._bridgeToObjectiveCImpl () -> Swift.AnyObject 0x1032ae470 <+48>: movq %rax, %r15 0x1032ae473 <+51>: movq %rbx, %rdi 0x1032ae476 <+54>: callq 0x10332706e ; symbol stub for: swift_unknownRetain 0x1032ae47b <+59>: movq %r12, %rdi 0x1032ae47e <+62>: movq %r14, %rsi 0x1032ae481 <+65>: movq %rbx, -0x38(%rbp) 0x1032ae485 <+69>: movq %rbx, %rdx 0x1032ae488 <+72>: callq 0x103326aaa ; symbol stub for: Swift.String._bridgeToObjectiveCImpl () -> Swift.AnyObject 0x1032ae48d <+77>: movq %rax, %r12 0x1032ae490 <+80>: movq 0x97881(%rip), %rsi ; "componentsSeparatedByString:" 0x1032ae497 <+87>: movq %r15, %rdi 0x1032ae49a <+90>: movq %r12, %rdx 0x1032ae49d <+93>: callq 0x103326f00 ; symbol stub for: objc_msgSend
Avatar
omochimetaru 4/3/2017 2:35 AM
それなら素直だな
2:36 AM
そのまんまなシンボルだ
Avatar
最後にobjc_msgSend
Avatar
omochimetaru 4/3/2017 2:36 AM
ひえっ
Avatar
そこからimplに流入してる
Avatar
omochimetaru 4/3/2017 2:36 AM
+80でレシーバ名リテラルをw
2:36 AM
可読性が高いアセンブリだ(?)
Avatar
String.componentsの、下の方見るとswift_rt_swift_dynamicCastClassとかあったりして
2:37 AM
なるほどーという感じ
2:39 AM
StringからNSStringのキャストと、NSArrayからArray<String>を持ってる
2:39 AM
String.componentsが見えない、参照できないのは
2:40 AM
Collectionにおける不可視のIndexと似た何かな?と思った
Avatar
omochimetaru 4/3/2017 2:41 AM
たしかにCmd+CLickでfoundationのトップが開いて
2:41 AM
シグネチャにとべないから
2:41 AM
変な事が起きてると感じてたけど
2:41 AM
飛べるはずのものが飛べない現象が他にもあるから
2:41 AM
これだけじゃなんとも言えないんだなあ
Avatar
2:42 AM
Foundationに何回か飛んだら見つけたわ
2:42 AM
import FoundationでFoundtationに飛んで、その中にあるimport Foundationからもう一回飛ぶと
2:42 AM
全部見えるようになった
Avatar
omochimetaru 4/3/2017 2:43 AM
ほんとだ!!
2:43 AM
なんだこれw
Avatar
カラクリだなぁ
2:43 AM
わからんよこんなの
Avatar
omochimetaru 4/3/2017 2:43 AM
めちゃめちゃ定義されとる
2:43 AM
2回飛ぶの
2:43 AM
覚えておこう
2:44 AM
あ、そもそも
2:44 AM
import Foundationの文から飛べば見えるわ
2:44 AM
メソッドのところからだと見えないバージョンの画面になる
Avatar
ひどい
Avatar
omochimetaru 4/3/2017 2:45 AM
(rintaroさんが知見を入力してる気配がする
Avatar
オーバーレイで定義されているメソッドに直行できないっていう単なる Xcode のバグなのかなと思っただけです。
Avatar
omochimetaru 4/3/2017 2:48 AM
直行できないだけじゃなくて、定義が無い空っぽ?のヘッダ空間みたいなものが出てくるんですよね
Avatar
これですけど、やってることは (self as NSString).components(separatedBy: separator)
Avatar
おおー
2:49 AM
_nsが生えてる
Avatar
omochimetaru 4/3/2017 2:49 AM
extension String { //===--- Bridging Helpers -----------------------------------------------===// //===--------------------------------------------------------------------===// /// The corresponding `NSString` - a convenience for bridging code. var _ns: NSString { return self as NSString } (edited)
2:49 AM
なるほど
Avatar
Xcode で飛んだときに上部に Foundation > String っていうパスが出ますけど、そんなものは無いと。
Avatar
omochimetaru 4/3/2017 2:52 AM
あ〜なるほど
2:53 AM
この何もない画面は Foundation/String
2:53 AM
いろいろ出てるやつは Foundation だから
2:53 AM
import Foundationから飛ぶと出てくるんですね 理解した
2:54 AM
てことは単純にクリックした時に 本当は Foundation の中の extension String に行くべきところが、 Foundation/String なページに飛ぼうとするところがバグっぽいですね。
Avatar
Xcode か SourceKit のバグですね。
Avatar
omochimetaru 4/3/2017 7:31 AM
@hiragram もしもし
Avatar
@omochimetaru もち
Avatar
omochimetaru 4/3/2017 7:32 AM
@tarunon それは確かに。ちょっと極端すぎる例だった。
7:32 AM
この話題最近俺も考えてた
7:32 AM
思うのは
Avatar
omochimetaru 4/3/2017 7:33 AM
うん
7:33 AM
APIに応じてフィールドが欠損したりする方と
7:33 AM
画面に表示するデータ構造をモデル化する方の型は
7:33 AM
別にせざるを得ないと思うんだよね
7:33 AM
扱ってるものが違うから
Avatar
うん
Avatar
元々の意味でのViewModelかな
Avatar
omochimetaru 4/3/2017 7:34 AM
そうだね、表示系の方はまさにViewModelかも。
Avatar
APIを扱うRepository層としてのエンドポイントのモデルと、アプリ内のデータ基盤としてのモデルがありそう
Avatar
omochimetaru 4/3/2017 7:34 AM
同意
7:35 AM
たぶん現在のSwiftの型システムでは
7:35 AM
現実のユースケースに対応しきれていない問題でもあると思ってて
7:35 AM
本当は欲しいのは
7:36 AM
一通りのキーが定義された型に対して
7:36 AM
静的に選択された一部のキーだけを持った
7:36 AM
部分構造型とでもいえばいいのかなあ
7:36 AM
そういうものが簡単な記法で生成できないと
7:37 AM
常に冗長なキーだらけの型で共通化したコードになっちゃう
7:38 AM
たとえば CommentListResponseの中の Comment.Userは名前しか持たないんだけど、そういう名前しかもたないNameOnlyUserに対して、完全なUserは User is NameOnlyUser な互換性がないといけない
Avatar
User型がエンドポイント毎に違って辛いのは
7:38 AM
User型単体ならそれほどでもないけど
Avatar
omochimetaru 4/3/2017 7:38 AM
プロトコルでシコシコ頑張ればできそうだけど記述量が多すぎる
Avatar
例えばTweet型にUser型が含まれる時に
7:38 AM
SearchとHomeTimeLineでUserの型が違うけどTweet型のプロパティは同じとかな
7:38 AM
そういうウンコみたいな状況が普通に発生し得る
Avatar
omochimetaru 4/3/2017 7:38 AM
うんうん。
7:39 AM
現状だと同じ部分について重複して書いた上で相互の変換メソッドを書き下す
7:39 AM
みたいになってしんどくなって
7:39 AM
ボトムタイプを作って逃げてしまう
Avatar
現状だと同じ部分について重複して書いた上で相互の変換メソッドを書き下す
それやってる つらい
Avatar
omochimetaru 4/3/2017 7:39 AM
ことになる
Avatar
Tweet<U: User>は有りなんじゃねーかなーとか
7:39 AM
考えたけどなぁ
7:40 AM
何れにしてもprotocol使ってHimotoki/Argoのアプローチだと
7:40 AM
重複したデコード処理書かなきゃいけなくなって辛い
Avatar
omochimetaru 4/3/2017 7:40 AM
Himotokiライクなデコーダは、例外的な事が起こらない時は機械生成可能だから
7:40 AM
それはそれでほしいよね
7:40 AM
Himotokiの、最もお行儀が良いスタンダードなパターンのdecodeメソッドについては手書きしたくない (edited)
7:45 AM
@hiragram ところでその、あるかないか未取得かの型は
Avatar
はい
Avatar
omochimetaru 4/3/2017 7:46 AM
enum NullableResponseField<T> { case .some(T) case .null case .notProvided } enum NonnullResponseField<T> { case .some(T) case .notProvided } とかやるか、 Optional<Optional<T>> とするしか無さそう (edited)
Avatar
そうそう
Avatar
omochimetaru 4/3/2017 7:47 AM
で、この2つを使ってフィールドを埋めまくった
Avatar
そこまでは発想できた
Avatar
二重Optionalは可読性が著しく下がりそう
Avatar
omochimetaru 4/3/2017 7:47 AM
struct UserResponse { var name: NonnullResponseField<String> var bio: NullableREsponseField<String> }
Avatar
二重optionalはやりたくないなあ
Avatar
omochimetaru 4/3/2017 7:47 AM
とかやって
Avatar
extension NonnullResponseField { var asOptional: E?? } ならまぁ。
Avatar
omochimetaru 4/3/2017 7:48 AM
protocol PartialResponseType { associatedtype ConcreteType } 的な何かで、 UserUserResponse を紐付けておくとなんか嬉しいところがあるかも・・・? (edited)
7:49 AM
ぐらいのところまでで考え中
Avatar
そうそう 大体そんな感じのことを考えていて、 NullableResponseField に当たる、Optionalみたいなパシッとした名前ないかなあというのが最初のツイート
7:50 AM
たるのん氏からAmbiguous案をもらったけど、若干エラーっぽい雰囲気があるのでもうちょっと他のないかなってかんじ
Avatar
omochimetaru 4/3/2017 7:50 AM
APIに依存した話だからOptionalみたいにセントラルな名前じゃなくて良い気がするなあ
Avatar
Optional<T> は T? みたいなシンタックスシュガーがあるけどこれから作るやつは無いからごちゃごちゃ長い名前を書きたくない というのがあった
Avatar
omochimetaru 4/3/2017 7:51 AM
なるほど。
Avatar
型シンタックスシュガー任意に作りてーと思ったけどあったらあったで混沌化しそう
Avatar
omochimetaru 4/3/2017 7:52 AM
使うファイルでだけ typealias K<T> = NulableResponseFiled<T> みたいな手はあるけどね
Avatar
シンタックスシュガー欲しい気持ちはあんまりないなあ 混沌化しそうわかる
7:53 AM
なぜK
Avatar
omochimetaru 4/3/2017 7:53 AM
Key
Avatar
なる
Avatar
omochimetaru 4/3/2017 7:55 AM
Absentable<T>
7:56 AM
Optionalの類義語探すだけになりそう。なんか有名なパターンとかないんかねえ。
Avatar
Optionalの類義語探すだけになりそう
そうなのよw
Avatar
omochimetaru 4/3/2017 7:57 AM
まあ、大事なのはその類義語に特別な意味を付与したってことをREADMEに書いておくことだから・・・
Avatar
エンドポイントによって型が違うのどーすんの問題にみんな悩んでいるということで安心した
Avatar
サーバーサイドをしばいてAPIを作り直させるというひどい方法もあります
Avatar
omochimetaru 4/3/2017 7:59 AM
Optionalだけ ? があってズルいっていうのはさもありなんだなあ
Avatar
Unbox使ってますがエンドポイントで変わりそうな箇所は全部雑にOptionalにしちゃってます
Avatar
omochimetaru 4/3/2017 8:14 AM
@moaible さっきのhiragramの要件では、実際に取得しなかったのか、値nullが入っているのかで、制御が変わる場面があるとのことです (edited)
Avatar
なんかOptionalにtypealiasつけて
8:15 AM
Maybeでもいいけど
8:15 AM
Maybe<T?>とかしておけば
8:16 AM
可読性そこまで犠牲にせずに済むのでは?って気もした
Avatar
あーそういうことですか... 🤔
Avatar
optionalにtypealiasってどゆこと
Avatar
omochimetaru 4/3/2017 8:16 AM
面白い
Avatar
typealias Maybe<T> = Optional<T>
Avatar
ああなるほど
Avatar
で、キーの有無についてはこれを使う
8:17 AM
まーコンパイラで制約違反を弾けないから微妙かな (edited)
8:17 AM
人間は怠惰で傲慢なので、決まりごとは守らないからコンパイラには厳しく躾けてもらう必要がある
Avatar
parser側で3パターンのenum(nonnull/nullable/responsenull)で定義したResponseFieldに合わせてdecodeするような作りだといまいちです?
8:43 AM
この例と被るのか enum NullableResponseField<T> { case .some(T) case .null case .notProvided } enum NonnullResponseField<T> { case .some(T) case .notProvided }
Avatar
omochimetaru 4/3/2017 8:43 AM
そうですね、あと、その3値enumの名前が悩ましいです。
Avatar
Swaggerとかだとnullableの属性が3.0から追加されるらしいのと、key自体の存在はrequiredだからrequiredの対義語とかだと通じやすかったりするんですかね
8:53 AM
ってなるとoptionalなのか...一周してしまう
Avatar
omochimetaru 4/3/2017 8:54 AM
そうなんですよね〜 omochimetaru - 今日 午後4時55分 Absentable<T> Optionalの類義語探すだけになりそう。なんか有名なパターンとかないんかねえ。 hiragram - 今日 午後4時56分 > Optionalの類義語探すだけになりそう そうなのよw
Avatar
やっと皆さんに追いついた感
8:58 AM
個人的には @omochimetaru さんが言ってた通りセントラルな名前じゃなくていい派ですね、用途が限定的なわけですし
APIに依存した話だからOptionalみたいにセントラルな名前じゃなくて良い気がするなあ
Avatar
omochimetaru 4/3/2017 8:58 AM
なるほど
Avatar
アプリ全体から見るとセントラルじゃなくていいけど、モデル層を別ターゲットに切り出してるのでそこでみると結構セントラルなのではという気がしている
9:00 AM
モデル層というかAPI叩く層
Avatar
レイヤー的に分けてるのであればAPIを意識した名前だと冗長なのも分かるし...うーん
Avatar
セントラルかどうかは僕はけっこうどうでもいい気持ちで名付けについては
Optional<T> は T? みたいなシンタックスシュガーがあるけどこれから作るやつは無いからごちゃごちゃ長い名前を書きたくない というのがあった
これに尽きる
9:02 AM
ところでdiscordって1メッセージに対するパーマリンクってどうやって取るの
Avatar
omochimetaru 4/3/2017 9:02 AM
見当たらないね>パーマリンク
Avatar
日付時刻を右クリックで取れるのが相場だろうが〜というきもちだ
Avatar
確かに
Avatar
うーん3値enumはダメな気がしてきた
11:01 AM
状態としては
11:01 AM
キーの有無とキーが存在する時にnullableである、という2つは独立であるはず
11:01 AM
なので、結局T??でしかない
11:01 AM
外側に名前をつけるべきなんだろう。
11:02 AM
typealiasはコンパイラ弱くなるから、型作るとしてもそれはKeyの有無を意味する型に留めるべき
11:02 AM
nullableはお前の仕事じゃねぇ
Avatar
omochimetaru 4/3/2017 11:02 AM
まあ理論的にはそうだよね
11:03 AM
Optionalの場合は3値で元々がNonnullの場合は2値で両方実装したりしないといけないし。
Avatar
いや
11:03 AM
T??って3値だよ
11:04 AM
switch x { case .none, case .some(.none) case .some(.some) }
Avatar
omochimetaru 4/3/2017 11:04 AM
enum NullableResponseField<T> { case .some(T) case .null case .notProvided } enum NonnullResponseField<T> { case .some(T) case .notProvided }
11:04 AM
3値方式だと、この2つを作らないといけなくなるってこと
Avatar
そうそう
11:04 AM
使いにくい、外側だけにして中身任意にしたほうが良い
Avatar
omochimetaru 4/3/2017 11:04 AM
クラスのプロパティの型が2重入れ子のジェネリクスになるのが微妙かなと思った
11:04 AM
ま〜でも Observable<Int?> とかも2重か
Avatar
まあ見た目はNullableResponseField<T?>になるし
11:05 AM
いいんじゃね
11:07 AM
ふーむ、大体わかってきた
11:09 AM
Genericsなnested classも作れるようになったし、その気になればなんとかなるかな?
11:09 AM
暇な時にもう一回試してみよう
11:10 AM
前回はうまく行かなかった
Avatar
omochimetaru 4/4/2017 1:43 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
1:44 AM
rejectされたwwwww
Avatar
w
Avatar
今朝Elica氏の哀しみのツイット見て笑った
Avatar
メーリスではみんないいねいいね言ってなかった?
Avatar
omochimetaru 4/4/2017 1:46 AM
Finally, the core team discussed a different potential design for “private” that admits a limited form of type-based access control within files. We will open a separate discussion thread on Swift Evolution, with the subject "Type-based ‘private’ access within a file", and are seeking further discussion there and a motivated volunteer to turn it into a new proposal for Swift 4.
1:46 AM
型ベースのファイル内アクセス制御の方式について考える事にした?
Avatar
さっき流れてた Type-based ‘private’ access within a file はコレか
1:47 AM
typeprivateみたいなのはほしいと思ってた
Avatar
omochimetaru 4/4/2017 1:47 AM
あ〜
1:47 AM
ある型から見えるみたいな?
Avatar
同じ型からじゃないかな
Avatar
お、それは欲しい
1:47 AM
extensionからもアクセスできるのね
Avatar
omochimetaru 4/4/2017 1:47 AM
C++の friend 文はけっこ〜闇だったけど
Avatar
struct Hoge { typeprivate var fuga: String } extension Hoge { func sayFuga() { print(fuga) } } みたいな?
Avatar
それがファイルを超えてアクセス可能なのか、ライブラリ超えたらどうなるのか
Avatar
これほしいとおもっていた 今までfileprivateにするしかなかったのがもにょもにょしてた
Avatar
が、気になる
Avatar
omochimetaru 4/4/2017 1:48 AM
とりあえず突っぱねただけじゃなくてもっと考えるぞっって感じなら良さそう
Avatar
within a file だから同一ファイルだけじゃないかな
Avatar
ほんとだ
Avatar
fileprivateだと同じファイルなら別の型からも見えてたけど、同一ファイルでかつ同じ型じゃないとみれないのがType-based ‘private’ access within a fileだとおもう
Avatar
omochimetaru 4/4/2017 1:49 AM
ちなさっきの引用はこのメールね>[swift-evolution-announce] [Rejected] SE-0159: Fix Private Access Levels
Avatar
omochimetaru 4/4/2017 1:50 AM
ああ、本スレにもそのまま書き込まれてんのか
1:50 AM
[swift-evolution] Type-based ‘private’ access within a file
Avatar
swift-evolution-announceなんてMLがあったのか(今知った)
Avatar
あんまりアクセス修飾子をぽこじゃか追加しても、多くの人間は結局まともに使えないとかならないかな
Avatar
Type-based ‘private’ access within a fileについてはむしろfileprivateの本来あるべき姿な気がするのでこれは歓迎
1:51 AM
むしろType-based ‘private’ access within a fileじゃなくてfileprivateじゃなきゃこまるようなシーンなくない
Avatar
それはわかる
Avatar
omochimetaru 4/4/2017 1:51 AM
@hiragram うん、僕はアナウンスしか取ってない
Avatar
名前がわかりやすくなるならそれで良い
Avatar
omochimetaru 4/4/2017 2:06 AM
スレの提案を読んだ
2:06 AM
* An extension of “X” in the same file * The definition of “X”, if it occurs in the same file * A nested type (or extension thereof) of one of the above that occurs in the same file This design has a number of apparent benefits: + “private” becomes the right default for “less than whole module” visibility, and aligns well with Swift coding style that divides a type’s definition into a number of extensions. + “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages: + It fits well with the "progressive disclosure” philosophy behind Swift: you can use public/internal/private for a while before encountering and having to learn about “fileprivate” (note: we thought this was going to be true of SE-0025 <https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md>, but we were clearly wrong) + When “fileprivate” occurs, it means there’s some interesting coupling between different types in the same file. That makes fileprivate a useful alert to the reader rather than, potentially, something that we routinely use and overlook so that we can separate implementations into extensions. + “private” is more closely aligned with other programming languages that use type-based access control, which can help programmers just coming to Swift. When they reach for “private”, they’re likely to get something similar to what they expect—with a little Swift twist due to Swift’s heavy use of extensions. + Loosening the access restrictions on “private” is unlikely to break existing code.
2:08 AM
・privateは同じファイル内のエクステンションからも見えるようになる ・fileprivateは元々同じファイル内で別々の型の間で可視性をつなぐためで、コードを読む人にとって注意する場所として警告するためのキーワードで、その役割は残す
Avatar
妥当な感
Avatar
omochimetaru 4/4/2017 2:08 AM
とか書いてある
Avatar
現状のコードとの互換性を壊さずより便利に、だとこれが精一杯じゃないの
Avatar
omochimetaru 4/4/2017 2:09 AM
で、「これだと完全なスコープprivate無くなっちゃうけど何か欲しい?」とか、意見くれやって感じ
Avatar
今のprivate相当のものはほしいなあ
Avatar
scopedとか追加すんの?
Avatar
omochimetaru 4/4/2017 2:09 AM
そこらへんは、意見をくれや〜ってのが >>1
Avatar
ふむー
Avatar
omochimetaru 4/4/2017 2:10 AM
スレは結構伸びてるからまだわからん
2:10 AM
でもSE159の話のときみんなextensionのことばっか言ってたしだいたいこれで良さそうな気がする。個人的には。 (edited)
Avatar
スコープprivateなくなっておっけーってこと?
Avatar
omochimetaru 4/4/2017 2:11 AM
俺的には無くて良い気がするなあ
2:11 AM
なんかそれがあると結局同じループしそう
Avatar
うーむ
Avatar
増えてもヒトには扱えない、かなぁ
Avatar
omochimetaru 4/4/2017 2:11 AM
なるべくscopedにしろ派 vs 拡張の余地を残せ派 vs 適切に考慮しろ派
2:12 AM
第一印象であってまだ深く考えられてはないです
Avatar
アクセス修飾子についてあんまり深く考察してないけど↑だとなるべくscopedにしろ派かなあ
Avatar
昨日のGenericsネタ、この定義で試してみました
Optional<T> は T? みたいなシンタックスシュガーがあるけどこれから作るやつは無いからごちゃごちゃ長い名前を書きたくない というのがあった
これは解決できてないのでなんともですが ↓修正版 protocol FieldProperty { associatedtype Value } struct Field<T> { enum Requirable: FieldProperty { typealias Value = T case some(T) case notProvided } enum Nullable: FieldProperty { typealias Value = T? case some(T?) case notProvided } }
(edited)
Avatar
nested使ってもっと便利に書けるかと思ったけどそんなに変わらずですね 😰 (edited)
Avatar
ザハ先生の踏んだ2つのバグやばすぎるのなー
11:11 AM
⚠️ It looks like there is significant number of regressions in Swift 3.1 compiler ⚠️ The problems occur in Release builds when optimizations are turned on. It looks like Debug versions work ok so f...
Avatar
deinitやばそう
Avatar
omochimetaru 4/4/2017 11:15 AM
その件に絡んでた人アップルのSwiftの人だった
Avatar
deinitもですが、NSErrorのキャストでクラッシュも相当
Avatar
最適化で結構問題起きるので、ReactiveSwiftとかではReleaseでCI回してます
Avatar
この間見つけた強制キャストとのコンボで確実にクラッシュさせられる
Avatar
Errorもさっき確認した
Avatar
omochimetaru 4/4/2017 11:16 AM
コンボw
Avatar
強制キャストで死ぬの確認してないけど、多分死んでるの_bridging系だから死ぬと思う
Avatar
3.1移行してるんですが3.0に上げた時より破壊的な変更な気がしてます
Avatar
破壊的、仕様が変更されたではなく、unstableという意味ですか?
11:24 AM
壊れ方は書いてる型に依存しそう
Avatar
主にSwiftTaskで書いてる箇所と、TableViewでenum利用してsectionとrowを分けてるところが全部ビルドエラーですね..
壊れ方は書いてる型に依存しそう
このパターンなのが否めないです
(edited)
Avatar
SwiftTaskはそもそも3.0対応してましたっけ
Avatar
一応branchはあって、tagは切られておらずです
Avatar
inamiyさんがまだ同僚だった頃に同僚だし質問できるからと採用したら、RxSwiftかReactiveCocoaに移住してねと言われた記憶
Avatar
oh...
Avatar
3.1からのtypealiasの件、wandboxで試してみました 下記のコードで3.0.2までは動きますが、3.1-devとXcode8.3ではエラーになります open class Hoge<T> { public typealias ErrorInfo = (error: Error?, isCancelled: Bool) var receiveError: ((ErrorInfo) -> Void)? } Hoge<String>().receiveError = { (errorInfo: Hoge.ErrorInfo) in print(errorInfo) }
3:50 PM
これは3.1でも通ります open class Hoge<T> { public typealias ErrorInfo = (error: Error?, isCancelled: Bool) var receiveError: ((ErrorInfo) -> Void)? } Hoge<String>().receiveError = { (errorInfo: Hoge<Any>.ErrorInfo) in print(errorInfo) }
3:52 PM
型変数を定義してるスコープ内の型にアクセスする際は、アクセスする際に型変数を埋めることが3.1から必須になったってことみたいです // o Hoge<Any>.ErrorInfo // x: 3.1〜Hoge.ErrorInfoとHoge<T>.ErrorInfoは区別する Hoge.ErrorInfo (edited)
Avatar
ネストしたGenerics型作れるようになったので、妥当な感
3:53 PM
前まで通ってたのが謎ではある
Avatar
確かに以前の方がアクセスできてしまうのはおかしい感あります (edited)
Avatar
スコープがジェネリクス型の中ならinner typeを自身の型を省略して書ける。typealiasの宣言場所がprotocolなら、自身の型を書かなければいけないが、型パラメーターは省略可能、スコープが外なら型パラメーター含め全て書かないといけない
4:14 PM
こんな感じだったはず
Avatar
omochimetaru 4/5/2017 1:19 AM
@omochimetaru @KrunoslavZaher @juliobailon Looks like Erik from the optimizer team just fixed it: https://t.co/oUFgxzYCE0
Avatar
リリース待ちか
Avatar
omochimetaru 4/5/2017 1:21 AM
こんなスピード感あると思ってなかった
Avatar
またファイルを分けるとコンパイルが通らなくなるバグを踏んでしまった
Avatar
omochimetaru 4/5/2017 11:58 AM
またw
Avatar
protocol extensionをファイル毎に分割して生やしまくると死ぬっぽい
11:58 AM
最小ケース探しの時間だ…
12:02 PM
12:02 PM
InstantiateTestsResourceをビルドすると再現できる。電車に間に合わなくなる前に会社でよ
Avatar
これもコンパイル順っぽいですね…
4:00 PM
つら
Avatar
昨日の、associatedtypeにTupleを与えてるのがどうも良くなかったらしく
12:02 AM
GenericsなTuple2を作って入れ替えたら素直に動くようになった
12:03 AM
Tupleを使ってるとPlaygroundも動いたり動かなかったりで、まだ調べないといけない。結論出たらまた貼り付けます。
👀 1
Avatar
omochimetaru 4/7/2017 12:58 AM
良さそうなプロポーザルがガシガシ来てる
Avatar
なんか今朝めっちゃ賑やかだった
Avatar
7本?一体何が起こったんだ・・・
Avatar
omochimetaru 4/7/2017 1:06 AM
昨日の夜と今日起きてからで半々ぐらいに別れた
1:06 AM
あっちでは1日かな?
Avatar
たぶんね。
1:07 AM
まだ一日終わってないと思う。
Avatar
omochimetaru 4/7/2017 1:08 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
最近 structindirect なプロパティほしいなぁと思ってるんだけどどうでしょう?
Avatar
omochimetaru 4/7/2017 1:09 AM
プロパティがインダイレクトってどういうことです?
1:09 AM
型定義のときに使うやつ?
1:09 AM
enumとかで。
Avatar
struct Hoge { let a : Hoge } ↑できない
Avatar
omochimetaru 4/7/2017 1:09 AM
あー
Avatar
@tarunon そうそれ。
Avatar
omochimetaru 4/7/2017 1:09 AM
Box挟めばいいけど
Avatar
enumindirect の導入で解決された
Avatar
omochimetaru 4/7/2017 1:10 AM
いや、それできちゃまずくない?
1:10 AM
enumは、caseによってループが終端するけど
Avatar
どういうシーンでほしいのか気になりますね
Avatar
omochimetaru 4/7/2017 1:10 AM
structだとループから抜けられない
Avatar
あー、 Optional じゃないといけないかも。
1:11 AM
あれ? Optional だと入れられるのか
Avatar
omochimetaru 4/7/2017 1:11 AM
indirectは実装が参照なだけで、実際にはヌルにならないから。
Avatar
なんか最近これが出来なくて困ったことがあって
1:11 AM
なんだったかな
Avatar
うん、僕も困ったことが最近あって
Avatar
omochimetaru 4/7/2017 1:11 AM
Optionalならそもそも普通に書ける気が
Avatar
エンドレスにはなってなかったはず
Avatar
Optionalなら書けそう
Avatar
SwiftScriptのASTで再帰的な構造が出てきて
1:12 AM
コンパイルエラーになって気づいたから
1:12 AM
何かできないことがあったはず。
1:12 AM
で、そのときは enum に逃がして解決したはず。
1:12 AM
ちょっと今時間ないので後で調べてみます。
Avatar
omochimetaru 4/7/2017 1:13 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
1:13 AM
これは例の0025の続きだな
Avatar
いやOptionalでも無理では
Avatar
1> struct Foo { 2. var bar: Int 3. var foo: Foo? 4. } error: repl.swift:1:8: error: value type 'Foo' cannot have a stored property that references itself struct Foo { ^
1:13 AM
ああそうか
Avatar
そう、Optionalで無理だから困ってた
Avatar
Optionalindirect じゃないからだ。
1:14 AM
indirectOptional を作れば解決するのか。
Avatar
omochimetaru 4/7/2017 1:14 AM
そのfooにindirectをつけたいということか
Avatar
indirect enum IndirectOptional<T> { case some(T) case none } struct T { let i: Int let a: IndirectOptional<T> }
1:15 AM
OK っぽい
Avatar
Avatar
omochimetaru 4/7/2017 1:15 AM
やっぱり
1:15 AM
ユーザー定義型構築演算子が
1:16 AM
ほしいね。
Avatar
そうなっちゃいますね
Avatar
omochimetaru 4/7/2017 1:16 AM
ww
Avatar
それか素Optionalが初めからindirectで、良いんじゃないって気がしたけど
1:16 AM
コンパイラの負荷が増大するかな
Avatar
うん、何がよくないのか今考えてました
Avatar
omochimetaru 4/7/2017 1:16 AM
それだと効率が悪い
1:17 AM
ペイロードがスタックに置けなくなる
Avatar
Optional で包んだ時点でヒープにいっちゃうのか
Avatar
あれ、よくわかってないんですが、Optionalがindirectじゃないって、じゃあなんで Hoge?? が書けるんですかね
Avatar
Optional<Optional<Hoge>>は別にループしてない
Avatar
omochimetaru 4/7/2017 1:19 AM
それはHogeがループしてるわけじゃないから
Avatar
あ、そうか
Avatar
Tがループする場合がindirectが要る
Avatar
理解です
Avatar
うーん
1:20 AM
IndirectOptional、普通に筋が悪い
Avatar
やっぱ↓みたいに書きたいなぁ。 struct Foo { var bar: Int indirect var foo: Foo? }
Avatar
indirect enum Foo { case Tail(int: Int, str: String) case Head(int: Int, str: String, foo: Foo) var int: Int { // switch書く } var str: String { // switch書く } var foo: Foo? { // switch書く } init(int: Int, str: String, foo: Foo?) { if let foo = foo { self = .Head(int: int, str: str, foo: foo) } else { self = .Tail(int: int, str: str) } } }
1:22 AM
Foo使う人にとってはこれが一番使いやすいな
1:22 AM
Fooを書く人は犠牲になってもらおう
Avatar
なるほど。
Avatar
omochimetaru 4/7/2017 1:23 AM
indirect var x : T? で良いと思う
Avatar
あればねw
Avatar
omochimetaru 4/7/2017 1:23 AM
同じこと書きたくないし。
Avatar
待ってる間、どう書くかを考えていて、IndirectOptional追加するのは
1:24 AM
使う側はしんどいなーと
Avatar
でも struct Foo { var bar: Int indirect var foo: Foo } はできないわけだし、ちょっとややこしそうだな。
Avatar
omochimetaru 4/7/2017 1:24 AM
なるる
Avatar
まあ、 enumindirect も同程度の理解を要求されるしいいのか?
1:25 AM
swift-evolution に投げてみてもおもしろいかも?
Avatar
indirect enum IndirectOptional<T> { case some(T) case none init(_ value: T?) { switch value { case .some(let t): self = .some(t) case .none: self = .none } } } extension IndirectOptional { var asOptional: T? { switch self { case .some(let t): return .some(t) case .none: return .none } } } struct T { var i: Int private var _a: IndirectOptional<T> init(i: Int, a: T?) { self.i = i self._a = IndirectOptional(a) } var a: T? { set { _a = IndirectOptional(newValue) } get { return _a.asOptional } } } 使う側も書く側も楽に出来た気がする。
1:30 AM
やっぱスッと書きたいですね
Avatar
Haskell とかだと問題にならない再帰的構造を作るときにひっかかっちゃうのは微妙ですね。
1:32 AM
Swift が値型で完結できる範囲を広げるには、やっぱり indirect プロパティほしいなぁ。
1:33 AM
enum も昔は参照で Box してたけど indirect で解決されたわけだから、 struct でだけ Box が必要って今の状況は変な気がする。
Avatar
omochimetaru 4/7/2017 1:34 AM
今ってindirectってプロパティじゃなくてenumの頭に付けてるんですよね?
Avatar
case にも付けられます。
Avatar
omochimetaru 4/7/2017 1:34 AM
なるほど
Avatar
enum IndirectOptional<Wrapped> { case none indirect case some(Wrapped) }
1:35 AM
↑のノリでプロパティにも indirect 付けたい。
Avatar
omochimetaru 4/7/2017 1:35 AM
今多分できてない理由の推測で
1:35 AM
indirectついたら、それは常にindirectなんじゃないかな
1:35 AM
おそらく、 indirect var a: Int?var b: Int? があるときに (edited)
1:36 AM
ab のメモリ上でのレイアウトが違っちゃって、 Int? に2種類のレイアウトがあることになるから
1:36 AM
うまいこと変換処理を挟まないといけないからとりあえず今は無いって木がする
Avatar
ん?? a だけアドレスになんじゃないの?
Avatar
omochimetaru 4/7/2017 1:36 AM
そのaを
1:37 AM
func f(x: Int?) に渡す時に
1:37 AM
あ、でも今もコピーしてるから同じか?
Avatar
struct Foo { var bar: Int indirect var foo: Foo? } のサイズは 64 bit 環境だと 16 バイト
1:37 AM
という想定。
Avatar
omochimetaru 4/7/2017 1:37 AM
いや、Fooのサイズは1種類だと思います。
1:38 AM
全然別の所で書かれた var xx: Foo?
1:38 AM
ポインタになってないって話し
Avatar
Foo? は 17 バイトでしょ??
1:38 AM
Foo は値型で、 Foo が 16 バイトだから。
Avatar
Foo.fooとxxで受け渡しするときに
1:38 AM
ポインタ型からOptionalへの変換が必要で
1:38 AM
これはまだない、ということ?
Avatar
omochimetaru 4/7/2017 1:39 AM
そう
1:39 AM
indirect Int?Int? の2つがあることを前提にコンパイラを修正しないといけない
Avatar
それって indirect case から値を取り出すときと何が違うの?
Avatar
omochimetaru 4/7/2017 1:39 AM
enumに関するindirectの場合は、「ついてない場合」を考えてない
1:39 AM
のではないかという推測
1:39 AM
常にBox型で取り回されてる
Avatar
indirect プロパティも「ついてない場合」なんてないのでは??
Avatar
omochimetaru 4/7/2017 1:40 AM
だから、単純に、indirectついてる場合をクラスと同じようにコンパイルするように切り替えるだけで良かった
1:41 AM
indirectプロパティは
1:41 AM
xxのような場合についてない。
1:41 AM
型に付いてるのではなく、プロパティについてるから (edited)
1:41 AM
型としては2種類ありえることになる
Avatar
indirect var foo: Foo?var foo: Box<Foo?> と読み替えるのでは?
1:42 AM
問題に鳴るのは
Avatar
indirectが書かれたpropertyを持ってる型はクラスと同じようにコンパイルする、とかだと上手くいくのかな
Avatar
値を変更するときだと思う。
1:42 AM
enum だと変更できない。
1:43 AM
いや、いいのか?取り出すときにコピーしてれば問題にならないか?
Avatar
omochimetaru 4/7/2017 1:43 AM
読み替えるついでに、Javaでいうところの AutoBoxingとAutoUnboxingの挿入が必要
Avatar
Box が取り回されるだけで。
Avatar
omochimetaru 4/7/2017 1:43 AM
enumにindirectを導入する際にはそのような修正は必要なかったけど
1:43 AM
プロパティにつける場合には必要になるから
Avatar
enum でもパターンマッチして取り出す時にアンボクシングしてるのでは?
Avatar
omochimetaru 4/7/2017 1:44 AM
実装の手間が違うから、とりあえずやらなかったんんじゃないか、という推測
1:44 AM
それは別に
1:44 AM
クラスからフィールド読むのと同じ
Avatar
indirectenum 全体が indirect されるわけじゃなくて、あくまで個別 caseindirect されるだけでしょ? (edited)
Avatar
omochimetaru 4/7/2017 1:45 AM
だからその個別のcaseが参照型だったと
1:45 AM
解釈できます
1:45 AM
でもそれは
1:45 AM
そのcaseは常にindirectだから
Avatar
caseに付けるときと、enumに付けるときとでバイナリに差が生まれるのか気になった
Avatar
だから、 struct でも個別のプロパティが Box だったと解釈すればいいんじゃないの?
Avatar
omochimetaru 4/7/2017 1:45 AM
そのcaseのindirectじゃないバージョンを考慮する必要がない
Avatar
プロパティの indirect じゃないバージョンも考慮する必要がないよ。
Avatar
omochimetaru 4/7/2017 1:46 AM
ありますよ
1:46 AM
だって Int? は実在してるから。 (edited)
1:46 AM
Fooの中で indirect Int? であっても、一般のInt?はそれとは別に存在する
1:46 AM
この2つは区別されて、適宜変換が必要
Avatar
だから、適宜変換が必要なのは enumcase も同じなんじゃないの?
Avatar
omochimetaru 4/7/2017 1:47 AM
いいえ
1:47 AM
caseは
1:47 AM
常にindirect
Avatar
enum に入れるときにはボクシングするし
Avatar
omochimetaru 4/7/2017 1:47 AM
それはassociated valueの話で
Avatar
だって、 enum そのものが indirect されてるわけじゃなくて
Avatar
omochimetaru 4/7/2017 1:47 AM
associated valueの話しはstructの中のフィールドの話し
Avatar
あくまで個別の caseindirect なだけだから。
Avatar
おもち君の言ってるのはassociatedvalueでkoher氏が言ってるのはenum型そのものやな
Avatar
enum Foo<T, U> { case bar(T) indirect case baz(U) }
1:48 AM
U だけ Box になる。
1:48 AM
enum Foo<T, U> { case bar(T) case baz(Box<U>) } ↑と等価。 (edited)
Avatar
enumはcaseから取り出すときにautounboxingを挟み込む余地があったから、楽だったのでは?
Avatar
うーん、それって struct のプロパティから値を取り出すときとそんな違いがありますか? indirect なプロパティなら unboxing すればいいだけな気が。
1:50 AM
ちょっと、昼までにやらなきゃいけない作業があるので離脱します・・・
Avatar
omochimetaru 4/7/2017 1:56 AM
enum-caseの場合は baz が indirectだからうんぬんってことを気にすればいいのが 明示的に記述される switch-caseでの分解の時だけってのが大きな違いだと思うって事
Avatar
enum Foo { indirect case bar(int: Int, str: String, foo: Foo) } この時に、barの中身が全部Boxingされてると仮定するなら、内側のFoo単体についてはBoxに纏わる何かを考えなくて良い。 従ってBoxが関わってるのは外側のFoo型でswitchなりif caseなりで一気になんとかできる。 structのpropertyとは別な印象があります。 (edited)
1:57 AM
SIL上でだけ存在する Box型があるみたい
Avatar
ン…
2:01 AM
でもswitch/if caseにBox処理入ってるのと,property { set get }にBox処理入ってるのそんなに違わない気がしてきたぞ
Avatar
omochimetaru 4/7/2017 2:02 AM
値型のプロパティアクセスって、
2:04 AM
house.cat.name = "tama" みたいなときのgetter/setterの差し込み , didSet等が無ければその省略
2:04 AM
とかあるから、ややこしそうな気がする
2:04 AM
常にcomputed property扱いにコンパイルしちゃえば同じ気がするね
Avatar
それで良い気がする
2:08 AM
メモリ周りの強化が入った時に
2:08 AM
プロパティの参照を取るってことができるようになりそうな気がしてて
Avatar
お…
Avatar
omochimetaru 4/7/2017 2:08 AM
その場合に、stored propertyとcomputed propertyで結構変わってきそう
2:09 AM
Rustの真似して、ある実体に対して、shared参照が複数、もしくは、inout参照が1つ、をフロー解析的に保証するとか書いてある (edited)
2:10 AM
func ==(left: shared String, right: shared String) -> Bool { ... } これとか面白い
2:11 AM
COWモデルのおかげで現状でもかなり早いと思うけど、これが入れば引数渡しのコストがC++に肉薄する
Avatar
pure funcを型レベルで保証するのってこの辺の話だっけ
Avatar
omochimetaru 4/7/2017 2:15 AM
それはまた別な気がする
2:16 AM
shared referenceで受けてる時は確かにそこから書き込めないから副作用が無いけど
2:16 AM
それで言うならSwiftの値型は常にコピー渡しだから普通に副作用無い
Avatar
まあそれはそうか
2:19 AM
sharedって、参照で渡すけど書き込み禁止って事だよね
Avatar
omochimetaru 4/7/2017 2:19 AM
です
2:20 AM
mutating funcが呼べない状態やね
2:20 AM
inoutは書き込める参照。現状仕様にあるやつ。
Avatar
今の何も書かない奴は、sharedと等価ではない?
2:20 AM
コピー走るからか
Avatar
omochimetaru 4/7/2017 2:21 AM
何も書かないやつはそもそも参照渡しじゃない
2:21 AM
値渡し(実体のコピーを伴う
2:21 AM
実体のコピーを伴うがCOWが仕込んであるからデータメモリまではコピーされないので話がややこしい。
Avatar
indirect property は現状これが一番現実的だと思う struct Foo { private var _inner: Any? = nil var inner: Foo? { get { return _inner.map { $0 as! Foo } } set { _inner = newValue } } } (edited)
Avatar
omochimetaru 4/7/2017 4:40 AM
お〜なるほど
4:40 AM
get { return _inner as! Foo? } はうまくいかないんですっけ?
Avatar
あ、いきますね
Avatar
そっか、privateならAny?でも問題ないか
Avatar
omochimetaru 4/7/2017 4:41 AM
AnyOptional<T> を入れる手と Optional<Any>AnyT にさせる手があるのかな
Avatar
as!アレルギー解除していかないと
Avatar
あーけどこれだとメモリ効率悪すぎるか。 Any に Any 込みの struct 入れたら絶対にヒープに入っちゃう。32バイト無駄すぎ。
5:17 AM
素直にBox作ったほうがいい気がしてきました。 これなら MemoryLayout<Foo>.size == 8indirect enum Box<T> { case val(T) init(_ val: T) { self = .val(val) } var val: T { switch self { case .val(let val): return val } } } struct Foo { private var _inner: Box<Foo>? var inner: Foo? { get { return _inner?.val } set { _inner = newValue.map(Box.init) } } }
👍 1
Avatar
@omochimetaru 前確かめた感じだとOptional<Any>のほうが筋が良かった。
5:22 AM
でもこの場合はBoxですね
5:23 AM
case 1個のindirect enum Boxすごい、脳汁出る
Avatar
omochimetaru 4/7/2017 5:28 AM
おおなるほど、まさに最適だ
Avatar
indirect のメモリ上の扱いの話ってどういうの見たらわかりますかね?
Avatar
omochimetaru 4/7/2017 6:47 AM
# 導入 Swiftには値型と参照型があります。また、Optionalはそれらと組み合わせてよく使われます。メモリ上ではどのように表現されているのでしょうか。調べてみました。(Swift 3.0.2) # メモリダンプ関数 メモ...
6:47 AM
↑これを真似すれば直接的なものは見れるよ
6:48 AM
あとはコンパイラを読むとかコンパイル後のLLVM-IRを読むとか。
Avatar
やっぱ基本的にはそーゆーアプローチになるのか
6:48 AM
ありがとうございます
Avatar
indirect enum Box<T> って class Box<T> じゃダメなんでしょうか? class 使わずあくまで値型で済ませるならってこと?
8:54 AM
あー、
8:54 AM
書き変えのときに
8:54 AM
いや、そんなことないか
8:54 AM
Box は隠蔽するからやっぱ class でも変わらないような?
Avatar
omochimetaru 4/7/2017 8:56 AM
BoxEは代入文でBoxEの実体も複製されて値的に振る舞うけど (edited)
8:56 AM
BoxCは代入文がBox自体の参照コピーになって
Avatar
ああ、そうか。コピーのときが問題なのか。
Avatar
omochimetaru 4/7/2017 8:56 AM
もともとのkoherがやりたいといった挙動と
8:56 AM
変わってる
Avatar
get, set のことばっか考えてた・・・
9:01 AM
Swift 1 で indirectclassBox で代替しても問題なかったのは、 enum がイミュータブルだからなのか。 (edited)
9:02 AM
もちろん Box そのものをいじっちゃったらダメだけど。
Avatar
omochimetaru 4/7/2017 9:02 AM
Swift1でもpattern matchしてBox自体をつかめば変な感じになりえますね (edited)
Avatar
多分 Swift 1 にパターンマッチはなかったです。
9:04 AM
あったんだっけ??どうやって enum の値取り出してたんだ??
Avatar
Swift1 でもパターンマッチはありましたよ。
9:44 AM
class Box でも大丈夫だと思います。Boxの中身がイミュータブルなら実用上は変わらないんじゃないかな。
Avatar
あれ?あったんですね・・・。
Avatar
2 で case let value? とかが追加になったくらい
Avatar
てっきり 2 で追加されたと勘違いしてました。
Avatar
omochimetaru 4/10/2017 2:07 AM
最近ふと気がついたんだけどSwiftのデストラクタがObjCの dealloc から deinit に名前が変わっている点について
2:07 AM
弱参照が残っている限りオブジェクトのペイロードメモリは解放されないから
2:08 AM
まさに dealloc じゃなくて deinit であるなあと気がついた
Avatar
それはdeallocの名前が不適切、ということ
Avatar
omochimetaru 4/10/2017 2:09 AM
UnsafePointer 周りの用語としても、 メモリ確保はAllocation/Deallocation、確保したメモリにオブジェクトをレイアウトする/剥がしてデストラクトするのが Init / deinit って用語がちゃんと揃ってる
Avatar
それとも呼ばれるタイミングがそもそも違う?
Avatar
omochimetaru 4/10/2017 2:09 AM
いやObjCも弱参照残っててもdealloc呼ばれるから
2:09 AM
そもそもdeallocじゃなかったわけなんだけど
2:09 AM
コレは仕方なくて
2:09 AM
iOS4以前は弱参照が無かったから
Avatar
確かに確かに
Avatar
omochimetaru 4/10/2017 2:09 AM
deallocされるときは絶対にメモリ解放されてたんよ
Avatar
言語仕様追加して名前と機能が噛み合わなくなった訳か
Avatar
omochimetaru 4/10/2017 2:10 AM
うんうん
Avatar
こんにちは
9:31 AM
Swiftのプロトコル、Compare+ableでComparableでしょ、Equate+ableでEquatableでしょ、Stride+ableがStrideableになるのってなんでなの
9:31 AM
これ気になってるんだけどだれか答え持ってませんか
Avatar
omochimetaru 4/10/2017 9:32 AM
なんちゃら XXXXeable ってよく間違えられてるから間違えてるのでは
Avatar
そうだよね
9:33 AM
MSにはStridableっていうなにがしかがある
Avatar
ぶ〜
9:33 AM
すごいな
Avatar
omochimetaru 4/10/2017 9:34 AM
ただ、たまに、
9:34 AM
アメリカ英語とイギリス英語で答えが違うとかあるから
9:34 AM
調べてみないとわからん
Avatar
そっちのほうがまだ信じられる
Avatar
Q&A for linguists, etymologists, and serious English language enthusiasts
😆 1
Avatar
convertibleとかあるし結構何でもありなのかも
9:38 AM
英語ネイティブじゃなきゃわからんきがする
Avatar
omochimetaru 4/10/2017 9:38 AM
swift-lang slackで意見聞けるかな
Avatar
正式な単語ではないからブレるのではという気も
Avatar
入ってないや > swift-lang slack
9:39 AM
送り仮名の揺れみたいなもんだな
9:39 AM
多分
Avatar
自動招待みたいなURLあったら教えて
11:27 AM
# 開催概要 potatotipsは 参加者全員がTipsを発表する というコンセプトのiOS/Androidアプリ開発者向けの勉強会です(ただし、最近はオーディエンス枠があります)。 今回はCyberAgent, Incさん主催での開催となります。 引き続き主催をいただける会社さんを募集中です。 (potatotipsの管理ページは コチラ です) # 内容 ## LT * 5分 × 発表者数で 2時間程度 * 途中で休憩を挟みます ## 懇親会 * LTフェーズ完了後に会場の時間の許す限り # 参加枠の種別 ## Tips発表枠 ### iOS/A...
❣ 3
Avatar
RxSwiftのCompleteableは直りましたね
Avatar
ものさんおるの?
Avatar
スパイから写真が来ました🥞
12:08 PM
僕は家です( ´・‿・`)
Avatar
スパイw
Avatar
Completeable治ったけど、[at]available書かずにやっちゃったからざわついてた
Avatar
omochimetaru 4/13/2017 3:07 PM
よくみたらものさんからスパイのヒント出てたっていうね
🥞 2
Avatar
SwiftのTupleは共変サポートされてないけど、クロージャの引数の型になっていればクロージャは半変サポートされているという話
12:39 AM
この間社内勉強会のえづらさんの会でたまたま気がついた
Avatar
omochimetaru 4/14/2017 1:07 AM
本当だw
1:07 AM
Swiftのタプル、いろいろあるべきものが足りてなくてたまに萎える
Avatar
コード補完が本当に雑魚い
1:11 AM
ラベル付きタプルをtypealiasに書こうものなら、いざコードを書くときに苦しみ抜いて死ぬことになる
😩 1
1:13 AM
仕方ないのはわかるから、再利用してinitが発生するような型パラにはTuple入れないでねってコーディング規約を最近提案した
Avatar
omochimetaru 4/14/2017 1:16 AM
なんか不便だから返り値とかにとどめて、 配列にいれて保持したりするならstruct定義してる たぶんその規約に従うとそうなりそう
Avatar
そう、返り値からメソッドチェインで次の引数になるような
1:16 AM
まさにmap/flatMapでは使うべき
1:17 AM
だけど、他の場所で宣言したものを入れる必要があるなら、struct作って、という感じ
Avatar
omochimetaru 4/14/2017 1:17 AM
本当にただパックしたい時だけって感じだよね
Avatar
tupleにinitが生えていてそれがコード補完されるなら、この規約はいらない
1:18 AM
Aliasからinit含むfunctionが補完されるか否かの差がめちゃくちゃ大きい。tupleだと無なので死ぬ
1:19 AM
まあそういうこともあって、上ので何か便利なworkaround産めないかと朝飯食いながら考えてるが、何も思い付かないw
Avatar
omochimetaru 4/14/2017 1:20 AM
ジェネリックマニフェストで、タプルにエクステンション書けるようにしたい、みたいな展望が書いてあって、 そこらへんの絡みで、ちゃんとした型に整備されたらいいなあ
Avatar
型パラにtuple入れるの、そう言えばそれ+αでコンパイラクラッシュするんだった
1:21 AM
struct Tuple2<A,B> ← 正直これ使いたくなるwww
Avatar
omochimetaru 4/14/2017 1:22 AM
C#とc++はマジでそれだけど使うと悲しくなるよ
Avatar
Javaもこんな感じじゃなかったっけ
1:23 AM
stdではないかな
Avatar
omochimetaru 4/14/2017 1:23 AM
気持ちはわかるけどそうなったらちゃんと名前つけた型つくる
Avatar
そう、Tuple2はラベルが付けられないのがダメ
1:24 AM
型推論はめちゃ強くなる
Avatar
omochimetaru 4/14/2017 1:24 AM
あーそれもあるか→ラベル
Avatar
型名は最悪typealiasでも良い
Avatar
omochimetaru 4/14/2017 1:24 AM
なるほど。たしかに。
Avatar
Genericsな実装があるメリットは大きい、でもラベル無いのが
1:25 AM
うーん
1:25 AM
まあ素直にstruct作るのが正解だな
Avatar
変性の話、↓もイケた。戻り値ならタプルも共変になる。 class Animal {} class Cat: Animal {} let cf: () -> (Cat, Cat) = { (Cat(), Cat()) } let af: () -> (Animal, Animal) = cf // エラーにならない let aa: (Animal, Animal) = af()
Avatar
omochimetaru 4/14/2017 2:23 AM
あ、じゃあそれを取り回せば・・・w
Avatar
おw
Avatar
普通のタプルが共変でないのなんでなんだろう・・・
Avatar
これは悪さが出来る
Avatar
omochimetaru 4/14/2017 2:24 AM
黒いなあ
Avatar
あ、Swift 3.0の方のマシンで試してしまった。3.1未確認。
Avatar
GenericsでU,T宣言してwhere U:Tが書けないから、出来ることが限られてるけど
2:25 AM
取りあえず大枠としての目標は、型消しで共変を無理矢理サポートさせるみたいな事がしたい。
2:26 AM
AnyHogeでラップしたら共編の範囲内で推論される
Avatar
タプルは値型だから var だったとしても共変で問題ないはずで、そもそもできないのが謎だけど何か理由があるのかな。
Avatar
あ、Swift 3.0の方のマシンで試してしまった。3.1未確認。
3.1でもイケるみたいです
Avatar
@moaible 確認ありがとうございます!
Avatar
omochimetaru 4/14/2017 2:27 AM
ドキュメントでそれに触れてるものを見たことはないです > 理由
Avatar
これは勝った
Avatar
↓値型と共変 class Animal {} class Cat: Animal {} class Dog: Animal {} var cats: [Cat] = [Cat()] var animals: [Animal] = cats // ここがコピーなので animals.append(Dog()) // これができても問題ない
2:28 AM
↑このコード、参照型言語の人が見たら発狂しそうw
Avatar
omochimetaru 4/14/2017 2:28 AM
そこのコピーってどうなってんだろう 共有してんのかな
Avatar
最終行でCoWで(実際の)コピーってのが理想だけど、どこでコピーが起こってるか確認したことはないなぁ。 (edited)
Avatar
omochimetaru 4/14/2017 2:30 AM
Swiftのclassはcovariance対応してないから
2:30 AM
Arrayのstruct部分の実Swiftコードで
2:30 AM
適切にその期待する挙動を書けない
Avatar
Array を Swift で実装するならってこと?
Avatar
omochimetaru 4/14/2017 2:31 AM
実際そうですよね?
Avatar
Array ってピュア Swift なんだっけ?違った気が。
Avatar
var cats: [Cat] = [Cat()] var animals: [Animal] = cats // ここがコピーなので_arrayForceCast() ってので実装されているので、cats.map { $0 } とほぼ同義です。 https://github.com/apple/swift/blob/master/stdlib/public/core/ArrayCast.swift#L30-L50
swift - The Swift Programming Language
Avatar
あ、そうですね
2:36 AM
Arrayの代入は暗黙的な変換です
2:36 AM
Arrayは引数と返り値の両方でTを使っているので
Avatar
おー、じゃあ先行してコピーされちゃうのかぁ。
Avatar
共変はない
Avatar
omochimetaru 4/14/2017 2:37 AM
おお
2:37 AM
@tarunon いや、COWにおいては最初のwriteをするまではreadonlyだから本来共変で共有できる
2:37 AM
writeする瞬間に共変性が破綻するのでコピーするっていうのが理想
Avatar
ふむ
2:37 AM
じゃあmapがlazyならokかな
Avatar
omochimetaru 4/14/2017 2:38 AM
Arrayがpure swiftだと思ってたのは勘違いだった
2:38 AM
というかソースを検索しても見当たらん
Avatar
実際試してみたけど、やっぱ代入時にコピーだ・・・。 import XCTest class SwiftCovariantCopyTests: XCTestCase { func testCopyWithoutAppend1M() { measure { let cats: [Cat] = [Cat](repeating: Cat(), count: 1_000_000) let animals: [Animal] = cats XCTAssertTrue(animals.last! is Cat) } } func testCopyWithAppend1M() { measure { let cats: [Cat] = [Cat](repeating: Cat(), count: 1_000_000) var animals: [Animal] = cats animals.append(Dog()) XCTAssertTrue(animals.last! is Dog) } } func testCopyWithoutAppend10M() { measure { let cats: [Cat] = [Cat](repeating: Cat(), count: 10_000_000) let animals: [Animal] = cats XCTAssertTrue(animals.last! is Cat) } } func testCopyWithAppend10M() { measure { let cats: [Cat] = [Cat](repeating: Cat(), count: 10_000_000) var animals: [Animal] = cats animals.append(Dog()) XCTAssertTrue(animals.last! is Dog) } } } class Animal {} class Cat: Animal {} class Dog: Animal {} Test Case '-[SwiftCovariantCopyTests.SwiftCovariantCopyTests testCopyWithoutAppend1M]' passed (0.592 seconds). Test Case '-[SwiftCovariantCopyTests.SwiftCovariantCopyTests testCopyWithAppend1M]' passed (0.790 seconds). Test Case '-[SwiftCovariantCopyTests.SwiftCovariantCopyTests testCopyWithoutAppend10M]' passed (4.162 seconds). Test Case '-[SwiftCovariantCopyTests.SwiftCovariantCopyTests testCopyWithAppend10M]' passed (6.556 seconds). (edited)
Avatar
_arrayForceCast() ってので実装されているので、cats.map { $0 } とほぼ同義です。
なので当たり前だけど。
Avatar
omochimetaru 4/14/2017 2:43 AM
appendの有無で変わらないと
Avatar
はい。計算量のオーダーが変わってなくて、純粋に append 分だけ遅くなってる。
2:43 AM
コピーが起こってなければ代入は O(1) 、コピーが起こってれば O(N) だから、 10 倍にしたときの増え方に変化が見られるはず。
2:44 AM
コピーというか、 map だから再生成って感じ?
Avatar
omochimetaru 4/14/2017 2:44 AM
ArrayはLazyCollectionじゃないからmapで普通に全コピー、であってる?
Avatar
最初のArrayのコンストラクトを measure 外に移したらどうなります?
Avatar
確かに。試してみます。
Avatar
omochimetaru 4/14/2017 2:45 AM
public var lazy: LazyRandomAccessCollection<Array<Element>> { get } これを使うとlazyになるのかあ。 (edited)
Avatar
ObjCランタイム(=Darwin)かつTがクラスなら #if _runtime(_ObjC) のほうに流れると思うのです。 (edited)
Avatar
lazyにしても、readした瞬間に遅延実行されない?writeじゃなくて。 (edited)
Avatar
実際にアクセスするまでmapのクロージャが走らないはず?
Avatar
swift - The Swift Programming Language
Avatar
omochimetaru 4/14/2017 2:48 AM
なんかそっちはバッファ共有っぽくみえる
2:48 AM
41行目の方は中身の保証があるからチェックなしの理想の共有で、 45行目の方は、アクセスに型チェックが挟まるのかな。Javaみたいな。
2:50 AM
Arrayのソースこれか?
2:51 AM
GYPになってるけど
public struct ${Self}<Element>
%{
arrayTypes = [ ('ContiguousArray', 'a ContiguousArray instance'), ('ArraySlice', 'an ArraySlice instance'), ('Array', 'an array'), ] }%
Avatar
Test Case '-[SwiftCovariantCopyTests.SwiftCovariantCopyTests testCopyWithoutAppend10M]' passed (0.624 seconds). Test Case '-[SwiftCovariantCopyTests.SwiftCovariantCopyTests testCopyWithAppend10M]' passed (2.282 seconds). Test Case '-[SwiftCovariantCopyTests.SwiftCovariantCopyTests testCopyWithoutAppend100M]' passed (4.037 seconds). Test Case '-[SwiftCovariantCopyTests.SwiftCovariantCopyTests testCopyWithAppend100M]' passed (23.242 seconds).
Avatar
omochimetaru 4/14/2017 2:51 AM
なんかここらへんが組み合わさってArrayのswiftコードが出てきそう
Avatar
初期化を measure の外に出した。
2:53 AM
いや、まちがえた
2:53 AM
これ measure の値じゃなかった
2:53 AM
普通に swift test が出してる値だった
Avatar
omochimetaru 4/14/2017 2:53 AM
Avatar
measure外で reserveCapacity() で +1 確保しておくと完全かと。
Avatar
Test Case '-[SwiftCovariantCopyTests.SwiftCovariantCopyTests testCopyWithoutAppend10M]' measured [Time, seconds] average: 0.000, relative standard deviation: 114.231%, values: [0.000023, 0.000005, 0.000003, 0.000003, 0.000003, 0.000003, 0.000003, 0.000003, 0.000003, 0.000003], Test Case '-[SwiftCovariantCopyTests.SwiftCovariantCopyTests testCopyWithAppend10M]' measured [Time, seconds] average: 0.163, relative standard deviation: 4.494%, values: [0.183134, 0.158554, 0.160044, 0.163250, 0.155895, 0.158189, 0.163386, 0.161289, 0.159981, 0.167179], Test Case '-[SwiftCovariantCopyTests.SwiftCovariantCopyTests testCopyWithoutAppend100M]' measured [Time, seconds] average: 0.000, relative standard deviation: 115.617%, values: [0.000020, 0.000003, 0.000003, 0.000003, 0.000003, 0.000003, 0.000003, 0.000003, 0.000003, 0.000003], Test Case '-[SwiftCovariantCopyTests.SwiftCovariantCopyTests testCopyWithAppend100M]' measured [Time, seconds] average: 1.762, relative standard deviation: 2.715%, values: [1.793434, 1.729103, 1.745168, 1.726823, 1.730955, 1.749660, 1.729168, 1.716899, 1.845567, 1.851858], (edited)
Avatar
最適化効いてるみたいですね。
Avatar
っぽいですね。 reserveCapacity はまだしてないです。 (edited)
2:57 AM
ということは、共変っぽい代入しても CoW が効いてると。
Avatar
@omochimetaru Arrayのソースはそれですが、 compiler intrinsic な処理もけっこう入るので Pure Swift とは言えない。
Avatar
omochimetaru 4/14/2017 2:57 AM
@rintaro ふむふむ
2:58 AM
_arrayForceCast って as! の時が基本の用途っぽいんですけど今回みたいな型安全な代入でも挿入されるのか今気になってて探ってるけどまだ手がかり無し
Avatar
む、 measure 外で reserveCapacity できない・・・。 animalmeasure の中で代入して生成されてるから・・・。
Avatar
-emit-sil %17 = function_ref @_TFs15_arrayForceCastu0_rFGSax_GSaq__ : $@convention(thin) <τ_0_0, τ_0_1> (@owned Array<τ_0_0>) -> @owned Array<τ_0_1>, loc "test.swift":7:27, scope 21 // user: %18 %18 = apply %17<Cat, Animal>(%14) : $@convention(thin) <τ_0_0, τ_0_1> (@owned Array<τ_0_0>) -> @owned Array<τ_0_1>, loc "test.swift":7:27, scope 21 // user: %19
Avatar
omochimetaru 4/14/2017 2:59 AM
おお!ありがとうございます
Avatar
cats で reserveCapacity しておけば、buffer 共有されているなら capacity 維持されるはずだから
3:01 AM
問題無いと思います。
Avatar
reserveCapacity したいのって、代入時にコピーが走ってるけど append でバッファのallocateが走ってしまってるから WithWithout で差が付いている可能性を排除したいってことですよね?
3:03 AM
代入時にバッファが共有されてる=CoWが効いてるのであれば、 append 時にはどのみち allocate されるから関係なくないですか?
Avatar
あー、ごもっともw
Avatar
あー
3:05 AM
Tupleで悪いことしようとしてたらまたコンパイラクラッシュした
Avatar
omochimetaru 4/14/2017 3:05 AM
すーぐ壊す
Avatar
今度はマジで天才だと思ったんだ
3:06 AM
undefined<T>以来のヒットだよ
3:06 AM
壊れたけど
Avatar
仮にコピーが走っているとすると 10M と 100M で差が出るはずですが、両方 0.000003 [s] だし、CoW効いてそう。観測下限って可能性もあるけど、さすがに100Mのコピーがこんなに速いことはない気がする。
Avatar
omochimetaru 4/14/2017 3:08 AM
C++と違ってユーザー定義コピーオペレータが書けないからそこがもどかしいんだよな
3:08 AM
C++なら Catの operator= とコピーコンストラクタと・・・ まあいろいろに printf しこめばはっきりする (edited)
Avatar
やりました
Avatar
omochimetaru 4/14/2017 3:09 AM
(ユーザー定義うんたらがあると Plainじゃなくなって動作が変わるかのうせいがあるけど
Avatar
型消しに共変性に近い機能を+する
Avatar
omochimetaru 4/14/2017 3:10 AM
後でみる
Avatar
@koher 上の最適化効いてるのは、catArrayの生成をmeasureの外に移した場合、ですか? (edited)
Avatar
omochimetaru 4/14/2017 3:27 AM
@tarunon 最適化はそもそも効いてたけど最初のArrayの生成が単純に重くて測定上のノイズになっていたという事
Avatar
あ、今気付いた。そうです。コードは↓。 import XCTest class SwiftCovariantCopyTests: XCTestCase { func testCopyWithoutAppend10M() { let cats: [Cat] = [Cat](repeating: Cat(), count: 10_000_000) measure { let animals: [Animal] = cats XCTAssertTrue(animals.last! is Cat) } } func testCopyWithAppend10M() { let cats: [Cat] = [Cat](repeating: Cat(), count: 10_000_000) measure { var animals: [Animal] = cats animals.append(Dog()) XCTAssertTrue(animals.last! is Dog) } } func testCopyWithoutAppend100M() { let cats: [Cat] = [Cat](repeating: Cat(), count: 100_000_000) measure { let animals: [Animal] = cats XCTAssertTrue(animals.last! is Cat) } } func testCopyWithAppend100M() { let cats: [Cat] = [Cat](repeating: Cat(), count: 100_000_000) measure { var animals: [Animal] = cats animals.append(Dog()) XCTAssertTrue(animals.last! is Dog) } } } class Animal {} class Cat: Animal {} class Dog: Animal {}
Avatar
ありがとうございます!
Avatar
上の最適化効いてるのは
これが、 Without の方が速かったのが、という意味ならその通りですし、 CoW が効いてるのがという意味なら @omochimetaru の言う通りどちらでも効いてて、生成が measure のノイズになっていたということです。
Avatar
CoW意図してました
3:31 AM
なるほど…
Avatar
omochimetaru 4/14/2017 3:32 AM
結論としては Linux版だと遅い
Avatar
Linux版だと遅い
これはどこから出てきたの?
Avatar
omochimetaru 4/14/2017 3:32 AM
ObjcRuntimeを積んでないから (edited)
3:32 AM
#if に入らない
Avatar
ObjCランタイム(=Darwin)かつTがクラスなら #if _runtime(_ObjC) のほうに流れると思うのです。
これか。
Avatar
omochimetaru 4/14/2017 3:33 AM
あい
Avatar
なるほど。そうじゃないと単純な map になっちゃうのか。
Avatar
omochimetaru 4/14/2017 3:34 AM
はい
Avatar
クラスじゃないとObjCに行かないなら、Cat/Animalをstruct/protocolで作ってる場合も同様に遅いのかな
Avatar
omochimetaru 4/14/2017 3:40 AM
そういうことだと思う
Avatar
omochimetaru 4/14/2017 3:52 AM
たるのんのさっきの gist やっと理解した
3:54 AM
いわゆるAnySequence<T> みたいなType Erasureを作るときに、AnySequence(cats) ってやると AnySequence<Cat> ができるけど、これの左辺をAnySequence<Animal> で受けたいってことね で、このパターンだと DogとDogAを足したときに、何も書き足さずに同じ仕組みでそれができると
Avatar
そうそう
Avatar
omochimetaru 4/14/2017 3:56 AM
・やりたいこと ・よく知られた手法で何ができないか を冒頭に書いてほしいでござるよ
Avatar
今までだと、多変数のprotocolだと多変数をバラバラに渡せばなんとかinit出来るみたいな
3:56 AM
すまんw
3:56 AM
状況であんまり嬉しくなかったのが、パラメータ1個渡せばいけるようになるから
3:56 AM
かなり便利
Avatar
omochimetaru 4/14/2017 3:56 AM
ちょっとかいてあったけどヒントが足りない
3:56 AM
ふむう
Avatar
UIKitのラップ周りで
4:01 AM
共変性持たせたいなーっていうシチュエーションが無限にあったので
4:01 AM
これはマジで嬉しい
Avatar
omochimetaru 4/14/2017 4:01 AM
あ〜
4:02 AM
AnimalとCatの代わりに UIView と UIImageViewとかがあって
4:02 AM
AnyXってのはViewModel<V: UIView> みたいな
4:02 AM
やつになる?
Avatar
ViewModelではないけど
4:02 AM
まっちくり
4:02 AM
一つはTransitioningAnimationの拡張周り
4:03 AM
この間SwiftTweetsで発表したやつの、3つ目の型変換が苦しかったのが
4:03 AM
ほぼほぼ解決する
Avatar
omochimetaru 4/14/2017 4:03 AM
ふむ
Avatar
これはSwift Tweetsの発表をまとめたものです。イベントのスポンサーとして Qiita に許可をいただいた上で、このような形(ツイートの引用)で投稿していま...
Avatar
ViewModelもGenericsで書いてたら嬉しいシチュエーションありそうだ
Avatar
omochimetaru 4/14/2017 4:19 AM
// こういうジェネリックなstructがあるときに struct S<T> { var s: T } var scat: S<Cat> = S<Cat>(s: Cat()) // ↓こんな事や var sani1: S<Animal> = sa // ↓次善でこんな事が var sani2: S<Animal> = sa.upcast() // できたらいいのにな (edited)
Avatar
そうそう
4:21 AM
C++だと
Avatar
omochimetaru 4/14/2017 4:21 AM
↑シンプルにこういう課題があると思うんだけど、簡単な解法がない・・・?
Avatar
Genericsパラメータに共変か反変かみたいなの
4:21 AM
書けるんだよね
Avatar
omochimetaru 4/14/2017 4:21 AM
std::enable_if<std::is_convertible<T, U>::value> なんかこんな雰囲気でできる。
Avatar
で、これ
4:22 AM
パラメータが1個なら
Avatar
omochimetaru 4/14/2017 4:22 AM
共変か反変かっていうのを概念として直接はかけないけど、代入可能かを静的に判定できるので、まあできる
Avatar
var sani1: S<Animal> = S(s: scat.s)
4:22 AM
まあこう書けばいいんで、そんなに苦じゃない
4:22 AM
でもパラメータが複数になると全部取り出すの辛いんだ
Avatar
omochimetaru 4/14/2017 4:22 AM
いや、1個でも苦しいよ・・・
Avatar
書いててだるい
4:23 AM
でー
Avatar
omochimetaru 4/14/2017 4:23 AM
まあフィールド数に比例してしまうのは終わってるね
Avatar
これをFunctionの共変/反変で判定するところまで持ち込んで、多変数でも1パラメータでいけるようにして、ってやったのが
4:24 AM
さっきの
Avatar
omochimetaru 4/14/2017 4:25 AM
C++で std::shared_ptr<Tp> から std::shared_ptr<Yp> へのアップキャストコンストラクタがこれ https://github.com/llvm-mirror/libcxx/blob/master/include/memory#L3531-L3535
Mirror of official libcxx git repository located at http://llvm.org/git/libcxx. Updated every five minutes.
Avatar
func some<T, U> (_ something: A<T>) -> A<U> where T: U
4:26 AM
こういうの書けないから今はFunctionに落とし込むしか無い
Avatar
omochimetaru 4/14/2017 4:26 AM
extension S { init<U>(_ o: S<U>) where T: U { self.init(s: o.s) } } // ↑これでいけるかとおもったけど駄目だった。 (edited)
Avatar
Tがprotocolじゃねーぞって怒られる
Avatar
omochimetaru 4/14/2017 4:27 AM
ですね。
4:27 AM
あくまでプロトコルコンフォーマンスだけがコンディションとしてかけて
4:27 AM
代入互換性が書けない事が問題と理解した
Avatar
functionの引数と返り値に関してはかなり強力な型チェックができるっぽいので
4:29 AM
それを頼るのが良さそう
Avatar
iOSアプリだとどうしてもクラスが出て来るけど、値型で書いてたらそもそも継承が出てこないから変性考える必要もない気も。
4:31 AM
プロトコル型で取り回すのもあんまりやらないし。
Avatar
まあ理想の世界はそうなんですがw
Avatar
omochimetaru 4/14/2017 4:32 AM
「iOSアプリだと」って、それが前提だからまあ・・・
Avatar
いや、なので、Swiftが変性まわりをないがしろにしてるのって、そういうこともあるのかなぁと。
Avatar
omochimetaru 4/14/2017 4:33 AM
ああ。Swiftyな世界ではstruct指向だからジェネリック型境界というテーマ自体の比重が軽いと
Avatar
はい
Avatar
omochimetaru 4/14/2017 4:33 AM
そういう意図は感じます
Avatar
とは言えclassが全く必要でないかというとそうでもなく
4:37 AM
現実の問題ではしばしばお世話になるはずなのでなんとかして欲しい
Avatar
ふと思いついたんですが、Swiftのタプルの辛みって「 (T, (S))(T, S) と同一視する」というルールを設ければ色々解決したりしませんかね
Avatar
今すでにそうなってるような。 type(of: (1, (2))) // (Int, Int).Type type(of: (1, 2)) // (Int, Int).Type
Avatar
(T)T と同一視する」はそうなってるんですが、それとは違って… と思ったけど言い方がよくなかったですね
12:45 AM
つまりタプルを単方向リスト的に処理できればいいんじゃない?という話をしたかったのでした (1,2) == (1, (2)) // 2 == (2) なので true (1,2,3) == (1,(2,3)) // Binary operator '==' cannot be applied to operands of type '(Int, Int, Int)' and '(Int, (Int, Int))' 下が通れば無限個のタプルを処理できるなーということです (edited)
Avatar
タプルは型として扱われてないから Equatable 準拠とか出来ないので == もタプルの要素数毎に定義されてますよね。(6要素まで) public func == <A : Equatable, B : Equatable, C : Equatable, D : Equatable, E : Equatable, F : Equatable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool { たぶんタプルを型として扱える様にしないとタプルのネストとか解決できない。
Avatar
はい、その6要素分の定義があまりにuglyなので… もし (A,B,C)(A,(B,C)) のシュガーシンタクスだと解釈できるようになれば、 public func == <A : Equatable, B : Equatable>(lhs: (A,B), rhs: (A,B)) -> Bool で全て賄えるはずだなと思ったんです、が… たしかにご指摘の通り、現状の言語仕様だとそもそもタプルをEquatable準拠させることが不可能なので、 B: Equatable が成立しないとこで詰みますね
1:17 AM
まあuglyなだけで、大抵は6要素分までのoperatorがあれば事足りるし、困ったら自分で拡張すればいいから、実運用上は何も問題ないってので今の実装なんだとは思いますけど
Avatar
Tupleが型Tuple2<A,B>になって、Conditional conformancesがある上でTupleNが全てTuple2の組み合わせのエイリアスなら成り立ちそうですが、これってバイナリツリーの平衡化とかも考えるんですか?効率は悪くなる気がしますね。
Avatar
omochimetaru 4/16/2017 6:18 AM
個人的には(A)と((A))はそのまま全く違う型なので、同一視はしないほうが嬉しいです 例えばjsonへの変換を考えると全く結果が違うし
6:19 AM
現状が型として不完全である問題の解決という意味なら、素直にタプルがらちゃんと型になってくれるほうが良いと思います
Avatar
omochimetaru 4/16/2017 6:30 AM
ああ一個だと同じなのか。ややこしいな。
Avatar
SE-0169がacceptされて読んでるけど英語大変
12:37 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
privateがextensionから見えるようになるよ、終わり!
12:51 AM
って感じに見える
Avatar
norio_nomura 4/18/2017 1:15 AM
fileprivate を使う機会を減らせそう
Avatar
@omochimetaru 多分言いたいのは ((A, B), C)(A, (B, C)) は違う型ということやんね?それは同意です。
2:05 AM
個人的にはタプルが nominal でないのは、タプルの乱用を防ぐためには理に適っているように思います。タプルを使うべきでないケースで struct を利用する圧力になっていると思う。
Avatar
omochimetaru 4/18/2017 2:05 AM
@koher そうです
2:06 AM
んん?
2:06 AM
仮にextensionが定義できるなど、型としてちゃんと扱えるようになったとしても
2:07 AM
ノミナルじゃないのはノミナルじゃないままで
2:07 AM
Swiftにおいてノミナルじゃない、というか、ストラクチュラルな型に対して、
2:07 AM
いろいろできない、
2:07 AM
という理解だったけど間違ってるかな
2:08 AM
それとも、 kotlinのPair<T, U>とかC#/C++のTuple2<T, U>, std::tuple<T, U> みたいな、ノミナルなタプル達を対比した発言?
Avatar
nominalじゃない=extensionが書けないの意図でした。
Avatar
omochimetaru 4/18/2017 2:09 AM
なるほど
2:10 AM
その下では、Swiftのtupleがいろいろ不便で、structへの圧力になってるという現状は僕もそう思っているけど、それがSwiftの設計思想上の意図なのか、単にズボラでこうなってるのかわからない
Avatar
norio_nomura 4/18/2017 2:14 AM
タプルって、メソッド呼び出し・戻りのペイロードを融通できるようにしたもので、効率が優先されるものだと想像。
2:15 AM
タプルを型として扱えるようにすると、その効率が維持できないと想像。
Avatar
omochimetaru 4/18/2017 2:15 AM
効率というのは実行速度の事ですか?
2:15 AM
それともコンパイル時間?
Avatar
norio_nomura 4/18/2017 2:15 AM
どっちもですかね。
2:16 AM
型にするとメタデータの生成が必要になり、それをメソッド呼び出し・戻りへ含めなければいけなくなる。 (edited)
Avatar
omochimetaru 4/18/2017 2:17 AM
他の struct 型と同様にそのような無駄なバイトは生まれないと思います (edited)
Avatar
norio_nomura 4/18/2017 2:19 AM
コンパイル時に型を決定できるならそうかもしれないけど
Avatar
omochimetaru 4/18/2017 2:22 AM
structと同様にfinal強制であれば大丈夫ですね
Avatar
値型なのにfinalでないこととかあるの??
Avatar
norio_nomura 4/18/2017 2:22 AM
プロトコルとか。
Avatar
protocolは値型ではないですね
2:23 AM
そもそもあれはただの型なので
Avatar
タプルの話ではなく??
Avatar
omochimetaru 4/18/2017 2:23 AM
@koher 値型なのにfinalでない事はありえないと思いますがそんな発言有った?
Avatar
@omochimetaru ↓これ。タプルの話だと思ってたから、当然そうだと思ってた。
structと同様にfinal強制であれば大丈夫
Avatar
omochimetaru 4/18/2017 2:25 AM
final強制と言っているのだから
Avatar
norio_nomura 4/18/2017 2:25 AM
タプルの中身がプロトコルの時とか、どういう扱いになるのだろう。
Avatar
omochimetaru 4/18/2017 2:25 AM
finalだというのが僕の意見ですよ。
Avatar
ああ、「であれば」が「だから」の意なのか。
2:26 AM
@norio_nomura それは struct がプロトコル型の stored property を持ってるのと同じじゃないですか?
Avatar
norio_nomura 4/18/2017 2:35 AM
あいや、今でもタプルのメタデータはちゃんと作られてるのか。
Avatar
omochimetaru 4/18/2017 2:35 AM
タプルの中身がプロトコルの時とか、どういう扱いになるのだろう。
プロトコルにassociatedtypeが無い場合しか無理なはずで、仮にprotocol P1 だったとすると、 var x: (P1, P1) の取扱は、 var y: P1 と、ただの単一変数が、 struct S { var y: P1 ; var z: P1 } とフィールドに並んだ場合と同じだと思います。
2:36 AM
メタデータってのは型の型の事ですかね、Anyに突っ込むことができるので存在はすると思います。
Avatar
norio_nomura 4/18/2017 2:38 AM
swift - The Swift Programming Language
Avatar
omochimetaru 4/18/2017 2:39 AM
おお。
2:39 AM
バイナリ表現まで規定されてるんですね
Avatar
norio_nomura 4/18/2017 2:39 AM
僕の認識は大きく間違っていました。
Avatar
omochimetaru 4/18/2017 2:40 AM
Tuple metadata has a kind of 9.
2:41 AM
Class metadata, instead of a kind, has an isa pointer in its kind slot, pointing to the class's metaclass record. This isa pointer is guaranteed to have an integer value larger than 4096 and so can be discriminated from non-class kind values.
2:41 AM
うわ、ここでも整数とポインタの同居が・・・
Avatar
norio_nomura 4/18/2017 2:44 AM
enum のペイロードもタプルだと思っていたのだけど、記述がない?
Avatar
omochimetaru 4/18/2017 2:45 AM
The nominal type descriptor is referenced at offset 1.
2:45 AM
ここからnominal type descriptorのところに
2:45 AM
For an enum:
2:45 AM
とかの節がありますが
Avatar
norio_nomura 4/18/2017 2:48 AM
For enums that are members of an enclosing nominal type, this is a reference to the enclosing type's metadata.
とあるので、複数型含む場合には enclosing type がタプルってことでいいのかな。
(edited)
Avatar
omochimetaru 4/18/2017 2:49 AM
ここは
2:50 AM
parentとか書いてあるし、enclosingっていうのは
2:50 AM
struct Cat { enum State {} } みたいな
2:50 AM
型の中の型の場合に
Avatar
norio_nomura 4/18/2017 2:50 AM
なるほど。
Avatar
omochimetaru 4/18/2017 2:50 AM
自身が定義される型の外側の型のメタデータを持つって記述では
2:50 AM
enum自体の中身がかいてああるのは、その一個上のoffset1のところで
2:51 AM
nominal type descriptorへの参照になってて、nominal type descritporの説明を読んでいくと、enumの場合について書いてありました
2:53 AM
あいや違う。
Avatar
omochimetaru 4/18/2017 2:53 AM
For an enum:
The number of payload cases and payload size offset are stored at offset 2. The least significant 24 bits are the number of payload cases, and the most significant 8 bits are the offset of the payload size in the type metadata, if present.
2:54 AM
↑こんなテキストのところ。
Avatar
norio_nomura 4/18/2017 2:55 AM
ありがとうございます
Avatar
omochimetaru 4/18/2017 2:57 AM
ABI周りって型のメタデータ一通りちゃんと規定する必要があるんだなあ・・・
2:57 AM
そりゃそうだよなあ大変そう
Avatar
norio_nomura 4/18/2017 2:57 AM
先に「ノミナル」って出てきてたのは Nominal Type Descriptor https://github.com/apple/swift/blob/master/docs/ABI.rst#nominal-type-descriptor を持つ型たち、ってこと?
swift - The Swift Programming Language
Avatar
omochimetaru 4/18/2017 2:58 AM
えーっと
2:58 AM
発端は @takasek さんの以下の発表で https://speakerdeck.com/takasek/what-is-a-nominal-type
❤ 1
2:58 AM
nominal type自体は
2:59 AM
型システム理論での概念で https://en.wikipedia.org/wiki/Nominal_type_system
In computer science, a nominal or nominative type system (or name-based type system) is a major class of type system, in which compatibility and equivalence of data types is determined by explicit declarations and/or the name of the types. Nominal systems are used to determine if types are equivalent, as well as if a type is a subtype of another. It contrasts with structural systems, where comparisons are based on the structure of the types in question and do not require explicit declarations.
❤ 1
2:59 AM
そこらへんを指して話していて
2:59 AM
僕はSwiftのNominal Type Descriptorとの対応でちゃんとは考えていませんでした。
2:59 AM
というか、そんなものがあるのは今しったw
3:01 AM
The kind of type is stored at offset 0, which is as follows: 0 for a class, 1 for a struct, or 2 for an enum. 結果的に認識とは一致していそう。タプルやファンクションはnon-nominalですね
Avatar
norio_nomura 4/18/2017 3:06 AM
「Swiftのタプルの辛み」をなんとかするには nominal type descriptor や protocol descriptor を持つ型にしないといけない雰囲気ですね。
Avatar
omochimetaru 4/18/2017 3:09 AM
non-nominalなままextensionとかが書けるようになったらいいと思うんですけどね
3:11 AM
GenericManifestoではそのトピックも上がっている
Avatar
norio_nomura 4/18/2017 3:12 AM
おお、まさにこれじゃん。
3:15 AM
Function typeにもextensionが欲しいと以前思ったことがあったんだけど "Extensions of structural types" っていう括りだと、それも含まれるのかな。
Avatar
omochimetaru 4/18/2017 3:16 AM
そう思います。
Avatar
Function typeはサブタイピングがあるからさらにややこしそう・・・
Avatar
omochimetaru 4/18/2017 3:18 AM
タプルもサブタイピングはほしくないですか?
3:18 AM
covarianceだから
Avatar
() -> Animal に対する extension() -> Cat にも使えるのか。
Avatar
omochimetaru 4/18/2017 3:18 AM
(Animal, Int)に対するextensionは(Cat, Int) でも使いたいですよね
Avatar
タプルは今のところ covariant になってないから、素直に考えればそれはないのでは?
Avatar
omochimetaru 4/18/2017 3:18 AM
あ〜
3:19 AM
Functionは今もう既になってるからか。
Avatar
うん
Avatar
Functionの引数と返り値のみ、何故かタプルもCovariantになりますけどね
3:19 AM
完全に謎
Avatar
omochimetaru 4/18/2017 3:19 AM
作りかけなだけだと思うんだよなあそこらへん
Avatar
引数と戻り値は、タプルだけどタプルじゃなくて、複数引数と複数戻り値なんでしょうね。
Avatar
omochimetaru 4/18/2017 3:20 AM
でも、そこがちゃんと区別されるようになりますよね
3:21 AM
今までは ( (A,B,C) ) -> R が (A, B, C) -> Rと同一視されてたけど
3:21 AM
(3要素タプルを引数に受ける関数 = 3引数関数)
3:21 AM
そこちゃんとわけようぜって方向に進んでる
Avatar
norio_nomura 4/18/2017 3:21 AM
メタデータではタプルになってますね
Avatar
omochimetaru 4/18/2017 3:22 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
3:23 AM
Swift's type system should properly distinguish between functions that take one tuple argument, and functions that take multiple arguments.
Avatar
あれ?↓もできるんだっけ?? class Animal {} class Cat: Animal {} let a: () -> (Int, (String, Cat)) = { (42, ("xyz", Cat())) } let b: () -> (Int, (String, Animal)) = a
3:24 AM
戻り値の一番外側のタプルはともかく、内側でも Covariant なの謎だ。
Avatar
そうそう
3:26 AM
引数も内側のタプルがそうなるんで
3:26 AM
謎だった
Avatar
これもできた。 let c: (Int, (String, Animal)) -> () = { _, _ in } let d: (Int, (String, Cat)) -> () = c
3:27 AM
なるほどー。関数型については、ネストした分も含めて、戻り値ではタプルは Covariant 、引数では Contravariant になってるんだ・・・。
Avatar
それ利用すると、Genericsのinitを関数で受け渡しすることで
Avatar
これ、 swift-evolution に出してもいいんでは? Inconsistent bihavior of tupple variances みたいな。
Avatar
GenericsにCovariant/Contravariantっぽい機能を追加できるようになる
Avatar
このまえやってたやつですね。
Avatar
そうです
Avatar
ネストの内側までこうなってるのって確信犯的ですよね。あえてやってる。
3:29 AM
ということは、普通のタプルでそうなってないのは実装漏れなのかな。
Avatar
で、それを書いてる途中で、またassociatedtypeにtupleを入れてdefault implを書くとコンパイラクラッシュに遭遇した
Avatar
omochimetaru 4/18/2017 3:29 AM
鉄板落ちみたいになってて笑う
Avatar
でも今回は、associatedtypeをBoxingすれば回避できることに気がついたので
Avatar
norio_nomura 4/18/2017 3:30 AM
stdlib内にその挙動を利用した実装があるのかどうか。
Avatar
この実装ができた。 https://github.com/tarunon/Covariancable
Covariancable - Add covariance/contravariance feature on your type-erasure.
3:30 AM
let convarianceAnimalCage = AnyAnimalCage<Animal>(~catCage) // Adding `~` operator, pass compile it! 💪
Avatar
omochimetaru 4/18/2017 3:33 AM
最後のめんどくさい部分を オペレーター定義で簡単にしたのね
Avatar
let foo: () -> (Cat, Int) = { (Cat(), 1) } let foo2: () -> (Animal, Int) = foo のときは -dump-astで (function_conversion_expr implicit type='() -> (Animal, Int)' (declref_expr type='() -> (Cat, Int)' )) だけど
❤ 1
3:33 AM
function_conversion_expr が噛まされているってことですね
Avatar
おー
Avatar
https://github.com/apple/swift/blob/master/lib/Sema/CSApply.cpp#L4427 みると、ASTで tuple を変換する expr が無いからまだ実装出来ないよ的な。
swift - The Swift Programming Language
❤ 1
Avatar
omochimetaru 4/18/2017 3:36 AM
// We need to convert the source element to the destination type. if (!fromTupleExpr) { // FIXME: Lame! We can't express this in the AST.
Avatar
Start factoring out the logic that computes the mapping from one tuple type to another. We're only using it in one place now (the tuple-to-tuple coercion), but it should be picked up by the constra...
❤ 1
Avatar
omochimetaru 4/18/2017 3:36 AM
FIXMEだ。
3:36 AM
てことは、やってないんじゃなくて、まだやってない、説が強くなってきたぞ
Avatar
じゃあ PR 作れば通る可能性も?
Avatar
忘れ去られているだけのような気がしますね。
Avatar
なるほどー。
Avatar
norio_nomura 4/18/2017 3:40 AM
素晴らしい
3:43 AM
この辺りの挙動は未定義で、たまたま今こうなってると。
3:47 AM
他と整合取れた実装にすると tarunon さんの Covariancable は動かなくなる?
Avatar
えっ
3:47 AM
TupleにCovariantが追加されるのが平和で良いのではないでしょうか
Avatar
omochimetaru 4/18/2017 3:47 AM
サブタイピングが効く側に倒れる分には動かなくはならなそうだけど、そもそも不要になりそう
Avatar
不要というか
Avatar
omochimetaru 4/18/2017 3:47 AM
効かない方に統一されたら動かなくなりそうですね
Avatar
中でfunction作って渡してる部分が、tupleでOKになるだけですね
Avatar
omochimetaru 4/18/2017 3:48 AM
あ〜
Avatar
効かない方に統一とか鬼畜の所業、やめていただきたく
Avatar
omochimetaru 4/18/2017 3:48 AM
そっか、taruninのライブラリがやるのはgeneric structのcovarianceの話か
Avatar
そうそう
3:49 AM
他パラメータ渡すのしんどいから~で簡単にする、でそれで受け渡しするのが
3:49 AM
tupleをreturnするfunctionから、tupleを使うだけの素直な実装になる (edited)
Avatar
前に Chris Eidhof が挙げてた Proposal が Review 入りしてる。これできたらうれしい。 https://github.com/apple/swift-evolution/blob/master/proposals/0171-reduce-with-inout.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
これは欲しい
3:56 AM
これが無いのでDictionaryを外に書かないといけない
Avatar
reduceDictionary 作る時とかだるすぎたから
3:56 AM
ですよね。
Avatar
norio_nomura 4/18/2017 3:59 AM
ASTで tuple を変換する expr が無いからまだ実装出来ないよ的な。
これって、タプルごとキャストが動かないのと同じもの? let anyany: (Any, Any) = (Int(1), Int(1)) if let intint = anyany as? (Int, Int) { print(intint) // 3.0.2: unreachable, 3.1: "(1, 1)\n" } if let int0 = anyany.0 as? Int, let int1 = anyany.1 as? Int { print(int0, int1) // "1 1\n" }
(edited)
4:00 AM
お、3.1で動くようになってた。
Avatar
キャストとはまた違う気がする
4:02 AM
でもキャスト動かなかったんですね、知らなかった
Avatar
norio_nomura 4/18/2017 4:05 AM
別物ですかね。 (edited)
Avatar
関係ありそうな気もしてきた、理解が半端だけど直感的にexpr無しで動かないような気もする。
4:10 AM
どうやって動くようにしたんだろ
Avatar
let a: (AnyObject, AnyObject) = (Cat(), Cat()) let b = a as! (Animal, Animal) みたいなときは、静的なキャストができなくてタプル全体が実行時キャストになるから FIXME のところまで到達しないと思います。 (edited)
Avatar
あー
4:26 AM
なるほど
4:26 AM
なるほど、なるほど
4:26 AM
ありがとうございます
4:26 AM
そうか、こっちはコンパイル時に解決しなくて良いのか
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
👍 2
Avatar
Array扱う分にはprefixdropで足りるんですけどね
Avatar
これが通ったらまたRangeファミリーが増えてしまう・・・。
Avatar
omochimetaru 4/18/2017 6:34 AM
ファミリーが多い問題点はconditional conformanceが入れば解決するのでは。
6:34 AM
特定のジェネリックなコードで4回オーバーロードしてるのが辛いって話ですよね (edited)
Avatar
はい。 conditional conformance で解決というのは?
Avatar
omochimetaru 4/18/2017 6:37 AM
1つの定義にできるような気がしてる
Avatar
protocol 作ればできる気がする。
Avatar
omochimetaru 4/18/2017 6:38 AM
あれっ、今ってprotocolすら何もついてないんですね
6:39 AM
今も自分でプロトコル付けたら1個にできるのかも
Avatar
protocol GeneralRange { associatedtype Value: Comparable var lowerBound: Value? var upperBound: Value? } extension Range: GeneralRange {} ... (edited)
Avatar
下限値はどっちも取れるんで上限値をとるのをつければ良さそうですね
6:41 AM
RangeClosedRangeupperBoundの意味が違った記憶
Avatar
単純な subscript だと 4 通りだけど、組みわせになると爆発するから https://github.com/koher/EasyImagy/blob/swift-3/EasyImagy/Image.swift#L78-L92
EasyImagy - Makes it easy to deal with images in Swift
Avatar
omochimetaru 4/18/2017 6:42 AM
/// An interval over a comparable type, from a lower bound up to, and
/// including, an upper bound. >> /// A half-open interval over a comparable type, from a lower bound up to, but /// not including, an upper bound.
6:43 AM
var includingUpperBound: Bool も生やせば解決? (edited)
Avatar
↑は本当は 16 通りある。↑は 2 乗だけど、 TensorSwift とか numsw でやってるようなのだと N 乗になっちゃうから一つにまとめないと実装できない。
6:43 AM
どうせなら 1<..42 とかも作って欲しい。
Avatar
下が開いてるのは需要ないんですかねぇ
6:44 AM
<..<まででてくると気持ち悪そう
Avatar
コーディング上少ないだけで、絶対にあると思うけどね〜。
6:45 AM
<.<<..< か悩ましいな。
Avatar
omochimetaru 4/18/2017 6:47 AM
1個点だともはやレンジ感が無くて謎なので2個がいいな
6:48 AM
僕は一般に範囲を制御する時は (begin, end): begin <= x && x < end とするのが好きで、理由はこれだと連続な直線を過不足なく繰り返し分割できるから
6:50 AM
したがって 4月いっぱいまでのキャンペーン期間を定義する時は 04-30_23:59:59 じゃなくて05-01_00:00:00にしたい (edited)
Avatar
つまり Range で事足りると言ってる?
Avatar
omochimetaru 4/18/2017 6:50 AM
そういう事ですね
6:50 AM
整数直線上で端が欲しい時はendを1個みぎにずらせばいいので。
6:51 AM
SwiftやRubyで記法があるときはまあClosedRange使うけれども別に型として存在して無くて良かった気がしてる
Avatar
それはそうなんだけど、それってそのスタイルが普及してるだけだし、普遍的に a<..b が要らない理由とはならない気が。 (edited)
Avatar
omochimetaru 4/18/2017 6:52 AM
まあそうですね。
6:53 AM
ライブラリのバージョン、みたいな、離散的で計数不能な数の指定において、そういう表現が欲しい可能性はある
Avatar
norio_nomura 4/18/2017 6:57 AM
SwiftPMのPackage.swiftでプレリリースバージョンの指定がうまくできなかったのを思い出す
Avatar
omochimetaru 4/18/2017 7:00 AM
ちょうどSPMのコードを最近眺めてたんで僕もそれを思い浮かべていました
7:02 AM
↑Range2種オーバロード
Avatar
norio_nomura 4/18/2017 7:05 AM
Still needs niceties like custom string conversion, fix out of date tests and add new ones.
Avatar
extension ${Self}: RangeExpression { こんな書き方初めて見た
7:12 AM
いやこれ自体はswiftじゃないのか
Avatar
omochimetaru 4/18/2017 7:13 AM
gypだね
7:13 AM
あっ、gypじゃなくてgybだ!
Avatar
Generate Your Boilerplate
7:14 AM
てっきりGoogleのGYPを流用しているのかと思っていた
7:15 AM
swiftプロジェクト内で作られたツールなんですね
Avatar
norio_nomura 4/18/2017 7:27 AM
swift.orgで配布されているツールチェーンのシンボルデータはgybから生成されたソースコードを指しているので、ツールチェーンのビルドなしにgybを適切な場所へ展開するツールとか作りました。 https://gist.github.com/norio-nomura/10d9790e7b5e414e20ae5ac6e621ef20 (edited)
swift_oss_helper.py helps debugging Swift Standard Library using source code with Swift Toolchain distributed at swift.org.
Avatar
omochimetaru 4/18/2017 7:28 AM
お〜
Avatar
norio_nomura 4/18/2017 7:49 AM
タプル続き class Animal {} class Cat: Animal {} let strinCat: (String, Cat) = ("xyz", Cat()) if let stringAnimal: (String, Animal) = strinCat as? (String, Animal) { print(stringAnimal) } でエラー: Playground execution failed: warning: 20170418-130912.xcplaygroundpage:1:50: warning: conditional cast from '(String, Cat)' to '(String, Animal)' always succeeds if let stringAnimal: (String, Animal) = strinCat as? (String, Animal) { ^ error: 20170418-130912.xcplaygroundpage:1:41: error: cannot express tuple conversion '(String, Cat)' to '(String, Animal)' if let stringAnimal: (String, Animal) = strinCat as? (String, Animal) { ^
Avatar
always succeedsとは
Avatar
norio_nomura 4/18/2017 7:51 AM
warning: conditional cast … always succeeds と言われるので as? から as へ変えると、2番目のエラーだけになる。 (edited)
Avatar
omochimetaru 4/18/2017 7:52 AM
実行時エラーじゃなくてコンパイルエラーですかね
Avatar
norio_nomura 4/18/2017 7:52 AM
です
Avatar
omochimetaru 4/18/2017 7:53 AM
ああ、本当だ、 always successなのに消しても怒られるw
Avatar
つらいw
Avatar
norio_nomura 4/18/2017 7:54 AM
先の FIXME: に引っかかってるぽいです
Avatar
omochimetaru 4/18/2017 7:57 AM
class Animal {} class Cat: Animal {} let strinCat: (String, Cat) = ("xyz", Cat()) print(strinCat) if let stringAnimal: (String, Animal) = strinCat as Any as! (String, Animal) { print("yatta") print(stringAnimal) } これでyattaが出力された・・・ (edited)
Avatar
そういえば、 "always failed" もバグってるんですよね。
Avatar
protocol Integral {} extension Int: Integral {} struct Foo<T> {} extension Foo where T: Integral { func foo() { let zelf = self as! Foo<Int> print(zelf) } } let foo: Foo<Int> = Foo() foo.foo() $ swift AlwaysFailed.swift AlwaysFailed.swift:8:25: warning: cast from 'Foo<T>' to unrelated type 'Foo<Int>' always fails let zelf = self as! Foo<Int> ~~~~ ^ ~~~~~~~~ Foo<Int>() (edited)
Avatar
今はT == Intできるから見なくなったやつですね
Avatar
omochimetaru 4/18/2017 8:10 AM
あー できるときもありえるのに絶対ダメでコンパイルできないのか
Avatar
いや、 warning
8:10 AM
でも、確か FooArray にするとコンパイルエラーになるという謎挙動だったはず。 (edited)
Avatar
extension Array where Element: Integral { func foo() { let zelf = self as! Array<Int> print(zelf) } } swift sandboxで何も言われない
Avatar
いや
8:12 AM
これやろうと思ったら
8:12 AM
unsafeBitCastしなきゃいけなかったはず
Avatar
aliasingとかの話ですか?
Avatar
let zelf = self as! Foo<Int>
8:17 AM
これですね
8:17 AM
ArrayはそもそもunsafeBitCast無理か
8:18 AM
unsafeBitCastはファントムタイプでwarningでなくなるのと無理やり動かせるだけだった
8:18 AM
勘違いス、すみません
👌 1
Avatar
この辺の話(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) らしいのですが、どういうケースなんでしょう? (edited)
Avatar
この元の話は variance の話ですよね?
8:40 AM
Farm<Cow>Farm<Animal> として扱えないという。
Avatar
です。
Avatar
で、 SevenTenEleven さんが言ってるのはこの前検証してたみたいな Array<Cow>Array<Animal> として扱っていい理由の話ですが、 CoW はあんま関係ない気がしますね。
8:41 AM
別に代入時にコピーしちゃえばいいだけだから。
Avatar
Farm が struct だった場合に Farm<Cow> as Farm<Animal> できるとして、どういう不整合が発生する可能性があるのかを知りたい。
Avatar
発生しない気がします。
Avatar
Farmの上位のprotocolの規約として、func some(_ t: T) が生えてる場合は困ったことになる気がする
8:44 AM
でもArrayは暗黙的なmapで別に困ってないのか
8:44 AM
ふむー
Avatar
二つ下で Core Team の Dave が func makeAllAnimalsSpeakInFarm(farm : Farm<Animal>) { farm.listenToAnimals() } じゃなくて func makeAllAnimalsSpeakInFarm<A: Animal>(farm : Farm<A>) { farm.listenToAnimals() } でいいんじゃない?って言ってる。この、サブタイピングに頼らずジェネリック関数で解決するの、 Swift 的に正しいと思う。 (edited)
Avatar
実際このCovariantが欲しくなるシチュエーション、Covariantにしなければいけない型の代わりにGenerics宣言するとスッと解決するんですよね (edited)
8:48 AM
ただまぁ、
Avatar
8, 9 割は↑で解決できるからプロトコル型変数自体も作れなくしちゃってもいいんじゃないかと思ってます。
Avatar
func some<T, U> (...) where T: U が書けないので
8:49 AM
引数に入れる側の型にGenericsを書かなければいけなくって、結構ウッてなる
8:49 AM
回りくどい
Avatar
omochimetaru 4/18/2017 8:50 AM
func some<T, U> (...) where T: U ←これのどこらへんが書けない?
Avatar
普通にコンパイル通りませんよ (edited)
Avatar
どういうときに使うんですか?
Avatar
Tがprotocolじゃないって怒られる
Avatar
omochimetaru 4/18/2017 8:50 AM
あ〜
Avatar
なんかでも最近それで怒られた記憶が・・・
Avatar
UIView/UIViewController周りで型パラでなんとかしたい~~ってなって、その辺でSwiftラッパー書いてると
8:51 AM
絶対遭遇しますね
8:51 AM
ラッパー側の汎ゆる場所をGenericsで宣言すればまあ動くんですが
8:52 AM
なので、func some<T, U> (...) where T == U って書いて、Uに束縛される側を、サブタイピングなGenericsで宣言し直す
8:52 AM
これが今のところ一番マシなWorkaround
8:52 AM
超回りくどい
Avatar
Generalized existentials↓を導入する方向性よりも、プロトコル型変数を禁止する方向性の方が、言語がシンプルになってうまくいくような気がしてる。さすがにサブタイピングなくなりすぎできついかな・・・。 https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials
swift - The Swift Programming Language
Avatar
classが存在する以上、問題はついて回りますね
Avatar
omochimetaru 4/18/2017 8:56 AM
@koher その章の例で示されているように、typealiasしちゃえば、 typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element> これって完全にあの書くのがめんどくさいTypeErasureの
8:56 AM
自動生成機能にすぎない気がします
8:57 AM
それともめんどくさい事によって濫用が防がれているのがいいのかな。
Avatar
initしなくていいっていう差はあるんじゃない?
Avatar
omochimetaru 4/18/2017 8:58 AM
あ、なるほど。
Avatar
あでも値型ならコピーするからほぼ変わらないのか
Avatar
omochimetaru 4/18/2017 8:58 AM
あくまで型関係なのか
8:58 AM
あー、うん、実行時モデルではそうなるけど
Avatar
データはともかくポインタは
Avatar
omochimetaru 4/18/2017 8:58 AM
プログラマがコンストラクタは書かなくていい
Avatar
それはそうね
8:58 AM
今は
8:58 AM
AnySequence(array)
8:59 AM
絶対こう
8:59 AM
で、これを利用者側に書かせるのがうんkだから、
Avatar
omochimetaru 4/18/2017 8:59 AM
あー、個人的にはむしろ、そこが大事な気がする・・・
Avatar
init<S: Sequence>(, , , sequence: S) みたいな
8:59 AM
そう言うの毎回作る
Avatar
omochimetaru 4/18/2017 8:59 AM
そこが明示的に変換していることでブリッジオブジェクトを生成しているコストが肌で感じられる
Avatar
APIのUXかな?(計算量の重い操作は使いづらい)
Avatar
omochimetaru 4/18/2017 9:00 AM
そうそう。
Avatar
TypeErasure自体アンチパターン感が。
Avatar
omochimetaru 4/18/2017 9:00 AM
で、この章のように、いらなくなってしまうと、
Avatar
ええーー
Avatar
omochimetaru 4/18/2017 9:00 AM
多分、ライブラリの引数で受けるところとか
9:00 AM
全部これで書きましょうって方向に
9:01 AM
みんな流れていく気がする
Avatar
引数はそのままで、格納するところはこれになるんじゃ
9:01 AM
だからあんまり変わらない気もする
9:01 AM
外見は一緒じゃないかなぁ
Avatar
多分、ライブラリの引数で受けるところとか 全部これで書きましょうって方向に みんな流れていく気がする
そう、こうなるのを恐れてる。
Avatar
omochimetaru 4/18/2017 9:01 AM
List<Integer> xs = new ArrayList<Integer>
Avatar
Java で List<String> とか書くノリで、 [String] じゃなくて AnySequence<String> になってしまいそう。
Avatar
omochimetaru 4/18/2017 9:02 AM
これの世界になってしまうと、値型ベースのSwiftの高速な世界が
9:02 AM
Javaのなんでもメソッドディスパッチコストかかる世界になっちゃいそう
Avatar
Java では次のようなコードが一般的です。 java // Java List strings = new ArrayList(); ArrayList インスタンスを `Arr...
Avatar
omochimetaru 4/18/2017 9:05 AM
引数はそのままで、格納するところはこれになるんじゃ
格納するところがこれになっちゃうと、遅くなるはず。
Avatar
ふむ
9:05 AM
今はAnySequence入れてるけど
9:05 AM
それは遅くならない?
Avatar
omochimetaru 4/18/2017 9:05 AM
今AnySequenceになっちゃってるならそれと同程度に遅い
9:05 AM
Arrayにしたほうが早いはず。
Avatar
ほー
Avatar
norio_nomura 4/18/2017 9:08 AM
これって、中身Arrayになるんじゃないの? (edited)
Avatar
Java 的な List<String> な世界を目指すなら Generalized existentials や Type Erasure はめんどくさすぎますし、サブタイピングに頼らない静的ディスパッチな世界を目指すなら Generalized existentials もプロトコル型変数すらもいらないと思うんですよねぇ。
Avatar
omochimetaru 4/18/2017 9:10 AM
@norio_nomura それは不可能なはずです。 SequenceはmakeIteratorでイテレーターが取れるっていうだけのインターフェースだから、 例えばmakeIteartorのたびに異なる数列を返すイテレーターを返す挙動がありえます。 AnySequenceのコンストラクタは S: SequenceS を受け取るだけだから、 その S の makeIteartorに転送するだけのコードがAnySequenceの実体です
9:11 AM
makeIteartorインターフェースは、無限数列も表現可能なので、そういういみでもArrayにできない
Avatar
norio_nomura 4/18/2017 9:12 AM
これの話だよね? typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element> let strings: AnySequence<String> = ["a", "b", "c"] (edited)
9:13 AM
今の AnySequence とは別物では?
Avatar
omochimetaru 4/18/2017 9:13 AM
あ、そっちの話か。すいません。
9:14 AM
そっちの場合は、現状で、 func f <E, S : Sequence> (s: S) where S.Iterator.Element == E とかやったときに、 これを呼び出す時に引数に渡したArrayがSequenceとしてアップキャストされるときと、 同じような仕組みで実現されると思っていて
9:15 AM
その場合、protocol existential 的なものになっていて、 元々のArrayもコピーしてるけど、メソッド呼び出しは いったんprotocol witness tableっていう、仮想関数テーブルを経由する形になります
9:16 AM
9:16 AM
# 導入 Swiftでは通常のプロトコルは変数の型として使用することができますが、 型パラメータ(associated type)を持つジェネリックなプロトコルの変数は作れません。 非ジェネリックな例 ```swift prot...
Avatar
9:18 AM
AnySequenceはmakeIteratorをclosureとして持つ構造じゃないの?
Avatar
omochimetaru 4/18/2017 9:18 AM
今のAnySequenceはそうだけど
Avatar
受け取ったSequenceからmakeIteratorを取り出す時にwitness-tableが要るのか
Avatar
omochimetaru 4/18/2017 9:18 AM
いや、2つのAnySeqneceの話があって
9:18 AM
今実在しているSTDLIBのAnySeqnceはクロージャーでメソッドを転送してるけど
9:19 AM
koherが張ったGenericManifestoで書かれてる typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element> Generic Existential + type alias としての AnySequenceは
9:20 AM
クロージャー方式じゃなくて、既存のジェネリック関数で引数のところで現れるメモリ表現になるんじゃないかなあという事
Avatar
AnySequenceが遅いっていうのは
9:21 AM
今のクロージャーを引き回すそれも遅いという事だと受け取ったんだけど
9:21 AM
それは違う?
Avatar
omochimetaru 4/18/2017 9:22 AM
どちらの方式でも遅い、という意見です
Avatar
ふむ
Avatar
omochimetaru 4/18/2017 9:22 AM
クロージャー方式でもwitness-table方式でも
9:22 AM
結局、プロトコルの型としてそのメソッドを呼べるようにするための関数呼び出しと、そこから、中で捕まえてる本当の型の対応するメソッドを呼び出すための、ブリッジするだけの関数の呼び出しが必要だから。
9:23 AM
witness-tableに入ってる関数ポインタの先にある関数の実装は
9:23 AM
結局、中身のArrayをダウンキャストで取り出して、Arrayの本当のメソッドを呼ぶ、っていう構造になってる。
Avatar
9:25 AM
クロージャー方式本当に遅い?
9:25 AM
クロージャーにキャプチャする時点で、関数ポインタの先にある実装を渡しているなら
9:25 AM
それほどクリティカルにならないんじゃね、と思ったんだけど
9:26 AM
_makeIterator = { _ in s.makeIterator() } ←これはクソ遅くなりそうだというのはわかるけど、 _makeIterator = s.makeIterator ←これはセーフでは?
Avatar
omochimetaru 4/18/2017 9:28 AM
AnySequenceの場合: AnySequenceのmakeIterator呼び出し→ _makeItaratorフィールドの関数を呼び出し → 内部でArrayのmakeItarotを呼び出し Arrayの場合: ArrayのmakeItarotorを呼び出し で、手数が増えてる。
Avatar
それは関数1個分のオーバーヘッドで
9:29 AM
tableの探索みたいなO(n)になり得るサムシングではない
Avatar
omochimetaru 4/18/2017 9:29 AM
それはそう
Avatar
遅いと言われたのでO(n)なのかと思った
Avatar
omochimetaru 4/18/2017 9:30 AM
それはJavaのList<Integer>でも同じ話で
9:30 AM
でも、そのオーバーヘッドが無いからこそ
9:30 AM
Swiftは C/ C++ と比肩するスピードが出せる
9:30 AM
設計上のポテンシャルがあるのが
9:30 AM
魅力だと僕は思っているので
9:30 AM
関数1個分とか2個分のジャンプが増えるのが嫌だ。
9:30 AM
という話し。
Avatar
norio_nomura 4/18/2017 9:31 AM
Generalized existentials はビルド時に型が決まれば specialize されたりしないのかな?
Avatar
omochimetaru 4/18/2017 9:31 AM
ジェネリック関数については基本的にspecializeされまくって消去されます。
9:31 AM
でも、外部からリンクしたときのために、柔軟なバージョンがオーバーロードされて残る。
9:31 AM
Generalized Existentialsも同じ事が言えるはずで
9:32 AM
特に型の中のフィールドとかで使われちゃうと
9:32 AM
public な struct とかだったら、無理ですね
9:32 AM
パッケージローカルなstructだったら、 Arrayで使われてる場合は、Arrayにspecializeされた版で動かして・・・という風に消去できれば、
9:32 AM
最高な可能性はあります
9:33 AM
それならC++のtemplate classと同じになりますね。
Avatar
norio_nomura 4/18/2017 9:33 AM
そういうものを目指してるのかと勝手に思ってました。
Avatar
omochimetaru 4/18/2017 9:33 AM
なるほど。
Avatar
norio_nomura 4/18/2017 9:33 AM
実際の実装が出てこないとわかりませんね。
Avatar
ちなみに、現状のstdlibの Any*** はクロージャー方式ではないですよ。
Avatar
ファッ
Avatar
class MyAnyIteratorBoxBase<Element> { func next() -> Element? { fatalError("abstract") } } class MyAnyIteratorBox<I : IteratorProtocol> : MyAnyIteratorBoxBase<I.Element> { var base: I init(_ base: I) { self.base = base } override func next() -> I.Element? { return base.next() } } struct MyAnyIterator<Element> : IteratorProtocol { var base: MyAnyIteratorBoxBase<Element> init<I : IteratorProtocol>(_ base: I) where I.Element == Element { self.base = MyAnyIteratorBox(base) } func next() -> Element? { return base.next() } } こんな感じ。
Avatar
うおお
9:36 AM
IteratorがAnyIteratorにinしてる…
Avatar
クラスのインスタンスメソッドへの動的ディスパッチが入るから、非常に遅い。
Avatar
かなしかった
Avatar
omochimetaru 4/18/2017 9:37 AM
クロージャーより遅くなるのでは
9:38 AM
クロージャーとくらべてvtableの方がis_aを手繰る分1メモリ操作遅い気がしてる
Avatar
Rationaleとしては、クロージャにするとメソッドが多くなったときに、Any*** 変数のMemoryLayout.size が非常に大きくなってしまうから。
9:39 AM
けど、Iterator は next() だけなんだし クロージャにしようよっていう議論がある。
Avatar
omochimetaru 4/18/2017 9:39 AM
なるほどなるほど。
Avatar
Generalized Existentialsのspecializeって難しくないですか?↓みたいな Foo<T> があったときに struct Foo<T> { var ts: Any<Sequence where .Iterator.Element == T> init(_ ts: Any<Sequence where .Iterator.Element == T>) { self.ts = ts } } ↓で作った ab の間で同じ型なのにメモリレイアウトを変えないといけなくなりません? var a: Foo<Int> = Foo(Array([2, 3, 5])) // Arrayにspecializeされる var b: Foo<Int> = Foo(Set([2, 3, 5])) // Setにspecializeされる a = b // どうなる??
Avatar
omochimetaru 4/18/2017 9:41 AM
たしかに。
9:41 AM
それをフィールドに持つ型 に ついては最適化不可能ですね
9:41 AM
ローカル変数とかぐらいなら・・・
Avatar
specializeできるケースって、ジェネリック関数で問題ないケースな気が。
Avatar
omochimetaru 4/18/2017 9:42 AM
ローカル変数ならそもそも生の型でいいんだな
Avatar
うん
Avatar
omochimetaru 4/18/2017 9:42 AM
specializeできるケースって、ジェネリック関数で問題ないケースな気が。
そんな気がしてきた
Avatar
norio_nomura 4/18/2017 9:44 AM
用途としては動的ディスパッチがメインってことですかね。
Avatar
用途としては動的ディスパッチがメイン
そうなるように思います。
Avatar
omochimetaru 4/18/2017 9:57 AM
おー、クリスエイドフが、クロージャーのほうが10%速いんだけど〜って書いてる。
9:58 AM
見てなかったけど swift-dev ML も面白いですね。
Avatar
norio_nomura 4/18/2017 9:59 AM
あれ? Generalized existentials って、今の AnySequence とかの延長なの?
Avatar
あれ? Generalized existentials って、今の AnySequence とかの延長なの?
ちがうけど、Generalized existential があれば AnySequence とかいらなくね?っていう文脈だとおもってます。
Avatar
ちがうけど、Generalized existential があれば AnySequence とかいらなくね?っていう文脈だとおもってます。
ですよね。ありがとうございます。
10:02 AM
swift-dev MLの「9割はCIが失敗した〜」です。
10:04 AM
ああ、AnySequenceの代わりになるなら、AnySequenceと同じ問題にぶち当たるだろう、ってことか。
Avatar
Farm が struct だった場合に Farm<Cow> as Farm<Animal> できるとして、どういう不整合が発生する可能性があるのか
あー、わかった
11:42 AM
class Animal {} class Cow : Animal {} class Sheep : Animal {} class Fence<T> { var animal: T? = nil } struct Farm<T> { var fence: Fence<T> = Fence<T>() } func buySheep(farm: Farm<Animal>) { farm.fence.animal = Sheep() } let farm = Farm<Cow>() buySheep(farm: farm as Farm<Animal>)
11:43 AM
Farm が Generic なクラスを持ってたらだめってことでした。
Avatar
それはfenceも同様にcovariantなら問題ないはず
11:44 AM
swiftのGenericsパラメータが、内部的にTがどのような使われ方をされてるかがわからなくて、多分一番問題になるのは
11:46 AM
struct Farm<T> { var 困る奴: (T)->() }
11:47 AM
こんな感じで、クロージャを持たせて引数にTを置くと、この場合はFarm<Animal>をFarm<Cat>に代入できるはずで、逆は成り立たない
Avatar
うむ。いずれにしても Farm.T を持つリファレンスタイプのプロパティは Farm のコピー時には 普通なら deep copy はされないからですね。 (edited)
Avatar
Tについて、covariantなのかcontravariantなのかが宣言できれば、無理なく機能を追加出来そう。 今やろうとすると、Generics型の変数と関数と場合によってはextensionすらチェックして、covariantかcontravariantなのかを判断することになるのかな、無茶っぽい。
11:55 AM
covariantなら、covariantなGenerics型と変数と返り値がTな関数が通る。 contravariantなら、contravariantなGenerics型と引数がTな関数が通る。
11:55 AM
これであってるだろうか…
Avatar
ああなるほど、Array<T>がいけるのに、任意のFarm<T>がダメなの、完全にクロージャがあり得るからだ
👍 1
12:18 PM
functionならパラメータ書き換えて安全に動くけどクロージャは無理だ
12:23 PM
と言うことは、stored propertyに関してのみ変性を確認すればokなはずで、であれば宣言無しでも現実的な時間に収束し得るかしら?
Avatar
@tarunon >Tについて、covariantなのかcontravariantなのかが宣言できれば、無理なく機能を追加出来そう。 C#やkotlinのdeclaration site varianceがまさにそういう設計ですね class Box<out T> {} みたいに、 Tの前に in か out をつけられる (edited)
Avatar
そうすると、引数のTをコンパイルエラーにできる
Avatar
オーバーライド可能なメソッドの返り値部分はそのままで、引数部分はcovariance/contravarianceが反転する
Avatar
正負の数としてイメージしたら解りやすいな、Out Tで、functionの引数にcontravarianceなTを入れるのはok
Avatar
http://docs.scala-lang.org/tutorials/tour/variances.html class Foo[+A] // A covariant class class Bar[-A] // A contravariant class class Baz[A] // An invariant class
12:46 PM
scalaはまさにそんな雰囲気の文法
12:47 PM
[ ]< > だと思えばOK
Avatar
おおーー超解りやすい
12:47 PM
最高じゃん
Avatar
マジかあw
Avatar
概念的にはまさにこれだ
12:48 PM
俺の脳内イメージにピッタリあったw過去最高に理解できた
Avatar
(マジかあの意図は 僕がkotlin派だからです) (edited)
Avatar
norio_nomura 4/19/2017 3:31 AM
Mirror って積極的に使っても良いものなのだろうか?
Avatar
リフレクションエンコーダーで結構使ってます
😮 1
Avatar
Farm が Generic なクラスを持ってたらだめってことでした。
なるほどー。↓値型のままだとわかりづらいので struct とイミュータブルクラスは等価だから書き変えて、 variance annotation ( out ) を付けて考えると Fenceanimal がコンパイルエラーですね。 setter が許容できない。 class Animal {} class Cow : Animal {} class Sheep : Animal {} class Fence<out T> { var animal: T? = nil // コンパイルエラー } class Farm<out T> { let fence: Fence<T> = Fence<T>() } func buySheep(farm: Farm<Animal>) { farm.fence.animal = Sheep() } let farm = Farm<Cow>() buySheep(farm: farm as Farm<Animal>)
Avatar
↓Kotlinでやってみた。 // Kotlin open class Animal() class Cow : Animal() class Sheep : Animal() class Fence<out T> { var animal: T? = null } class Farm<out T> { val fence: Fence<T> = Fence<T>() } fun buySheep(farm: Farm<Animal>) { farm.fence.animal = Sheep() } fun main(args: Array<String>) { val farm = Farm<Cow>() buySheep(farm) } 予想通り Fenceanimal でコンパイルエラー。 $ kotlinc NestedGenerics.kt NestedGenerics.kt:6:17: error: type parameter T is declared as 'out' but occurs in 'invariant' position in type T? var animal: T? = null ^
Avatar
セッターもそうなるのか
3:51 AM
そうか、そうですね。
Avatar
out な型パラメータは引数でつかえず、 in な型パラメータは戻り値で使えません。
3:51 AM
が、 contravariant なパラメータは反転するので、 Foo<in T> だったときに
Avatar
セッターに関して言うと、外から処理が差し込まれるわけじゃないので
3:52 AM
Arrayと同じような扱いにしてしまっても
Avatar
out T の型の中で Foo<T> を引数として使うことはできます。
Avatar
問題はないのでは、と思っていた
Avatar
引数や戻り値に関数型が来る場合も簡単で、 (T) -> UFunction<in T, out U> と読み替えれば OK です。
Avatar
お、 Swift でも T について covariant な Foo<T>Foo<out T> のように振る舞う)を作ることに成功した。 typealias Foo<T> = () -> T class Animal {} class Cat: Animal {} let a: Array<Foo<Cat>> = [] let b: Array<Foo<Animal>> = a // OK
Avatar
見た目がそれっぽいだけw
Avatar
それっぽいだけですが、 variance の挙動は確認できますね。 class Animal {} class Cow : Animal {} class Sheep : Animal {} class Fence<T> { var animal: T? = nil } typealias Farm<T: Animal> = () -> Fence<T> func makeFarm<T: Animal>() -> Farm<T> { return { Fence<T>() } } func buySheep(farm: Farm<Animal>) { farm().animal = Sheep() } let farm: Farm<Cow> = makeFarm() buySheep(farm: farm) // Fenceがinvariantなのでfarmもinvariantでコンパイルエラー
Avatar
おおー
Avatar
Fence を covariant にしようとして typealias Fence<T> = () -> T? にすると、今度は animalvar にできません( FecceTout である制約が効いていると解釈できる)。
Avatar
OptionalをAnyに突っ込むと、Mirrorでしかnilかどうかチェックできないっていうのもあって、この間うちの人がハマってた
Avatar
値型の variance 、どう考えたらいいのか難しいと思ってたけど、イミュータブルクラスに変換して、 mutating funcstatic メソッドに読み替えれば解釈できそう。 ↓ Array は covariant にできる class Array<out E> { func get(_ index: Int) -> E { ... } static func set<E>(_ this: Array<E>, _ index: Int, newValue: E) -> Array<E> { ... } } けど、 Fence は covariant にできない。 class Fence<T> { var animal: T? = nil } class Farm<out T> { let fence: Fence<T> = Fence<T>() // Fence が T について invariant なのでエラー }
Avatar
CoWだから実際の動きもこれに近いですよね
4:33 AM
Fenceは
4:35 AM
class Fence<out T> { func getAnimal() -> T? { ... } static func setAnimal(_ this: Fence, newValue: T?) -> Fence { ... } } このように定義しておけば、 Farm<out T>も成り立ちそう。
Avatar
↑だと Fencestruct と等価になってしまって、最初の「不整合」なケースの前提が崩れてしまいます。逆に言えば、 Fencestruct なら struct Farm は covariant 的に振る舞っても問題ないということですね。 (edited)
4:38 AM
ちなみに、 Java の配列は variance 周りがぶっ壊れてるので、コンパイルエラーで検出できずに実行時エラーになる。 class Animal {} class Cat extends Animal {} class Dog extends Animal {} public class CovariantArray { public static void main(String[] args) { Cat[] cats = { new Cat() }; Animal[] animals = cats; animals[0] = new Dog(); // 実行時エラー System.out.println(cats[0]); } }
Avatar
private extension Hoge: FugaProtocol {} こういうのできたらいいのになーって思ったことないですか
7:33 AM
'private' modifier cannot be used with extensions that declare protocol conformances
Avatar
omochimetaru 4/19/2017 7:35 AM
FugaProtocolの種類によってはObjCではよく思った
7:35 AM
例えば MainViewController : UITableDataSource みたいなのは、自分で持ってるTableViewに繋ぎこむだけの場合
7:35 AM
UITableDataSourceとして他のところでMAinViewControllerを使われても困るから
7:36 AM
特にそのconformanceを公開したい意図は無い
Avatar
そんなかんじ
Avatar
omochimetaru 4/19/2017 7:36 AM
Swiftの場合もし徹底したければ、そのプロトコルを満たしたAdapterオブジェクトを作ってhas-aにするかな
Avatar
やっぱそれしかないよなあ
Avatar
omochimetaru 4/19/2017 7:36 AM
それで外からは非対応に見える
7:37 AM
ObjCならimplementsを.mの方に書けばそうなった
7:37 AM
C++はprivate継承っていうまさにそれをやる機能があったりする
Avatar
↓はどうでしょう? fileprivate protocol Foo { func foo() -> Int } extension Int: Foo { fileprivate func foo() -> Int { return self } }
Avatar
手元でのケースは、一応複数のVCに対して適合させたいプロトコルなのでプロトコル自体をfileprivateにするのはう〜んってかんじがしますね
7:39 AM
Protocol conformanceをprivateにできたらいいなあというのはそれそのものをprivateにしたいというのとは別に、「プロトコルで実装が強制されるプロパティをprivateにしたい」というのもある
7:39 AM
protocol extensionからprivateが見えないからどうにもならない感じはする
Avatar
omochimetaru 4/19/2017 7:40 AM
プロトコルは外から見た制約だからprivateで満たすっていうは変な感じ
Avatar
プロトコル、外からどう見えるかというのもそうなんだけど、共通の実装を強制するみたいな側面もあると思っていて、そうすると外に見せる必要はないんだけど内部でこのプロパティは必要だから置いておいてねというのができたい
Avatar
omochimetaru 4/19/2017 7:41 AM
あーでも発想としては同じなのかな。Selfスコープだけでみたときにはselfをその型として渡せるって感じかな
Avatar
今プロトコルは internal で、それをある特定のファイルの中だけで満たすよう( fileprivate )にしたいというニーズということですか?
Avatar
omochimetaru 4/19/2017 7:42 AM
共通の実装を強制するみたいな側面
うーんなんかアンチパターンを感じる
Avatar
大体そうです
7:42 AM
koherさん
Avatar
omochimetaru 4/19/2017 7:43 AM
XxxMixIn とか XxxImplHelper みたいな形にしておいて必要部分のクロージャーを受け取るようにしてhas-aで持つとか。 (edited)
Avatar
protocol Hoge {} private protocol PrivateHoge { var xxx, yyy, zzz } extension Hoge where Self: PrivateHoge { ... } (edited)
7:44 AM
こういうのじゃダメなの
Avatar
xxxとyyyとzzzをその適合してるクラスのそとから見えないようにしたいんだけどできるんだっけ
Avatar
あー、そっち側があったか。その xxx とかつけるの逆に考えてて( Hoge につけるの考えてて)、だめだなぁと思ってた。 (edited)
Avatar
private protocol Testable { var test: Int { get } } extension MyVC: Testable { fileprivate var test: Int { return 1 } }
7:46 AM
ここまでならいけるっぽい
Avatar
要は「別ファイルにあるexntensionから見える」というアクセス修飾子があればいいだけな気がしてきた
7:48 AM
またアクセス修飾子の話になってしまった
Avatar
omochimetaru 4/19/2017 7:49 AM
ちょっとぐらい見えすぎても大丈夫だよ!
Avatar
やっぱだめだ。
7:49 AM
private protocol をより広い protocol が継承するのは変だ。
Avatar
継承はしてないっすよ
7:50 AM
広いprotocolはfunctionを定義していて、private protocolはその条件になるあれやこれやを書いていて、その両方をimplしたらメソッドが生える
7:50 AM
それだけです
7:51 AM
逆にprivate protocolがpublic protocolを条件付けしていたほうが、もっとシンプルに書けるかもしれない。
Avatar
元々の要望は Hoge を色んなところで使いたくて、それをある場所では private に使いたいという話だと思うんですが、
7:51 AM
そうすると PrivateHoge から Hoge に流す部分で、
7:52 AM
それを元々 Hoge が使いたかった箇所から可視にすることができない気がします。
Avatar
ああ、本当だ読み間違えていた
7:52 AM
implを中で持つしか無いなぁ
7:54 AM
class MyViewController { class ScrollViewDelegateImpl: UIScrollViewDelegate { let parent: MyViewController } lazy private (set) var scrollViewDelegate: ScrollViewDelegateImpl = { [unowned self] in ScrollViewDelegateImpl(self) }() }
Avatar
SE-0104 Protocol-oriented integers がmasterにマージされたんですね。 https://github.com/apple/swift/pull/3796#issuecomment-294096066 チューニングはこれからやりますと。
Work on integers from @moiseev What's in this pull request? Resolved bug number: (SR-) Before merging this pull request to apple/swift repository: Test pull request on Swift continuous integr...
Avatar
マージされて羨ましい。apple/swiftへのPRが初めてマージされそうなのに、僕の変更と関係ないところでSwift Test and Mergeが通らなくてやきもき。
👍 1
11:55 PM
Swift Test and Merge通ってなさすぎ。 https://ci.swift.org/view/Pull%20Request/job/swift-PR-merge/
Avatar
Protocol-oriented integers には Comparable の変更含まれていないのね。 (edited)
Avatar
omochimetaru 4/20/2017 1:15 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
ほしい
Avatar
欲しいなぁ
1:16 AM
webViewからjs叩くとき、こういうのが欲しい
1:16 AM
みんなどうやってんだろ
Avatar
+= でがんばってるんじゃない
Avatar
omochimetaru 4/20/2017 1:17 AM
シェーダーを書くときに欲しい
Avatar
配列でそれっぽく書いてたりしました
Avatar
配列なるほど
Avatar
omochimetaru 4/20/2017 1:31 AM
let str = [ "hello \(name)", "world" ].joined(separator: "\n") 配列はこうかな
👍 1
Avatar
omochimetaru 4/20/2017 1:39 AM
addDisposableToに変わって作られたdisposed(by:)ってAppleのAPI Design Guidelineに則ってなくない?
Avatar
Avatar
omochimetaru 4/20/2017 1:39 AM
@hiragram これめっちゃ気に入ってるんだけどマジ?
Avatar
マルチライン文字列リテラルがレビュー入り
レビュー前からされてなかった? Accepted なのでは?
1:40 AM
The review of SE-0168: "Multi-Line String Literals" ran from April 6...12, 2017. The proposal is accepted with revisions.
Avatar
@omochimetaru 則ってね~じゃんと思っていて https://swift.org/documentation/api-design-guidelines/ の "Name Mutating/nonmutating method pairs" のところ
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
omochimetaru 4/20/2017 1:41 AM
swift-evolution-announce] [Accepted] SE-0168: Multi-Line String Literals
1:41 AM
Acceptedだった。
Avatar
ガイドライン通りに読むと hogeDisposable.disposed(by: fuga) は「fugaによってdisposeされたhogeDisposable」が返るってことにならんかなあとおもって
1:42 AM
hogeArray.reversed() と同じ
Avatar
bindToがbind(to:)になったならaddDisposableToもaddDisposable(to:)になるのかなと思って見たらdisposed(by:)とかいうのが追加されてたのを発見したという感じ
Avatar
Accepted with revisions だから修正が必要ってこと?
Avatar
omochimetaru 4/20/2017 1:43 AM
disposeBagによって 後で dispose される だから確かに当てはまってないね、結果的に返り値とかもでないし
Avatar
// Allowed, equal to "foo\nbar" """ foo bar """ // Not allowed """foo bar """ // Not allowed """ foo bar"""
1:45 AM
- The core team also believes that underindentation or inconsistent tab/space usage within the indentation should be an error. Every line inside the literal must begin with the exact sequence of spaces and tabs that precedes the closing delimiter.
1:46 AM
インデントを含まないなら冒頭のスペースどうすんだろうと思ったんだけど、終わりの """ をベースに考えるってことかな?妥当な気がする。 (edited)
Avatar
インデント気持ち悪いと思ったけど変数代入することを考えると悪くないか。
Avatar
むしろインデントが含まれちゃう系のヒアドキュメントとか気持ち悪いと思ってたから良さそう。
Avatar
var x = """ hogehoge """"
1:48 AM
最後の"""は一つ落としたい感じが
Avatar
omochimetaru 4/20/2017 1:48 AM
これは後ろの """ を左に寄せとけば、余計な事しない?
Avatar
最後の"""は一つ落としたい感じが
そうだね。で、それができると。
Avatar
omochimetaru 4/20/2017 1:49 AM
一番左にベタ寄せのほうがコピペ安定性が高くて好きなんだけど
Avatar
これは後ろの """ を左に寄せとけば、余計な事しない?
そうじゃないかな?
1:49 AM
どっちもできるという意味で素晴らしい。
Avatar
omochimetaru 4/20/2017 1:49 AM
そうだと嬉しい
Avatar
Kotlin みたいなキモいことしなくていいのうれしい。 // Kotlin val text = """ |Tell me and I forget. |Teach me and I remember. |Involve me and I learn. |(Benjamin Franklin) """.trimMargin()
1:52 AM
閉じ """ でコントロールっておもしろいなぁ。
Avatar
"""の中なら、"はエスケープしなくても良いのかな、可読性一気に上がりそう
Avatar
omochimetaru 4/20/2017 1:53 AM
assert( xml == """ <?xml version="1.0"?> <catalog> <book id="bk101" empty=""> <author>\(author)</author> <title>XML Developer's Guide</title> <genre>Computer</genre> <price>44.95</price> <publish_date>2000-10-01</publish_date> <description>An in-depth look at creating applications with XML.</description> </book> </catalog> """ )
1:53 AM
提案がこうなってるし DQx2は書けるっぽい
Avatar
サイコーだ
1:54 AM
それも踏まえた上での3つか
Avatar
omochimetaru 4/20/2017 1:54 AM
っぽい
Avatar
norio_nomura 4/20/2017 1:54 AM
// Allowed, equal to "foo\nbar" """ foo bar """"foo\nbar\n" ではなく "foo\nbar" なのか。
Avatar
うん、そこがミソじゃない?
Avatar
omochimetaru 4/20/2017 1:54 AM
@norio_nomura 主流派とは違う感じがしますね
Avatar
あ、 @omochimetaru かと思ったら @norio_nomura さんだったw
Avatar
omochimetaru 4/20/2017 1:55 AM
失礼ですぞ
Avatar
失礼しましたw
Avatar
norio_nomura 4/20/2017 1:55 AM
お?
Avatar
必ず最終行に """ を書かせることでインデントをコントロールできるところがミソかと。
Avatar
後ろで揃える以上強制で\n入るのは微妙そうですしね
Avatar
omochimetaru 4/20/2017 1:56 AM
@t.ae いや、他の言語だと """aaa bbb""" これで "aaa\nbbb" になる。
Avatar
1行目インデント揃えれないの辛そう
Avatar
はい。それでswiftの仕様だとそれができないので
Avatar
うん、なので、 Swift の閉じ """ でインデントと本文を区別させる方式なら
1:57 AM
最後に "\m" を入れるわけにはいかない。最後の "\n" を消す方法がなくなっちゃうから。
Avatar
まさにそれが言いたかったことです。
Avatar
let s = """ abc def """ 今の仕様ならこれで末尾 "\n" が実現できるし。
Avatar
norio_nomura 4/20/2017 1:58 AM
納得
Avatar
Kotlin みたいな trimMargin もいらないし、これはうまい仕様だなぁ。
Avatar
norio_nomura 4/20/2017 1:59 AM
SwiftLintのテストケース書くのが一気に楽になる。
Avatar
いちいちファイル用意しなくて済みますね
Avatar
↓これどゆこと??
- The quoted string should normalize newlines to \n in the value of the literal, regardless of whether the source file uses \n (Unix), \r\n (Windows), or \r (classic Mac) line endings. Likewise, when the compiler strips the initial and final newline from the literal value, it will strip one of any of the \n, \r\n, or \r line-ending sequences from both ends of the literal.
// equal to "foo\nfoo\nfoo\nfoo" """^J foo^M^J foo^J foo^M foo^M """
Avatar
omochimetaru 4/20/2017 2:03 AM
ソースコードの改行コードによらず \n に正規化する
Avatar
^J とか ^M とか何?
Avatar
omochimetaru 4/20/2017 2:03 AM
^M が \r で ^J が \nのエスケープ表記かな?
Avatar
ああ、どっかに書いてあるのか?
Avatar
omochimetaru 4/20/2017 2:03 AM
gitのdiffで見る
2:04 AM
いや、なにかの流派におけるエスケープ表現 シェル系のだと思う
2:04 AM
詳しくは知らない
Avatar
あー、これを書けるようにしようというわけではなく、改行文字を表すためにここに書いてるだけってこと?
Avatar
omochimetaru 4/20/2017 2:04 AM
そう
2:04 AM
見えない文字を表現したくてそうなってる
Avatar
vimで改行コード不揃いのファイル開いた時に見たりする。
🙂 2
Avatar
なるほど。
Avatar
@hiragram disposed(by:)、本当はisDisposed(by:)が正しいんだと思う。
Avatar
omochimetaru 4/20/2017 2:08 AM
@tarunon isつけたらBool返す系になっちゃわない?
Avatar
そう、だからis抜いて意味がわからなくなった
2:09 AM
経緯見てないからわからんな
Avatar
omochimetaru 4/20/2017 2:09 AM
メソッド自体は Disposable を DisposeBagに突っ込む機能だよ
Avatar
Disposableが何を契機にdisposeするのか、とも取れる
2:10 AM
disposeBagはdisposeを発火するための装置、であれば、まあ納得かな
Avatar
omochimetaru 4/20/2017 2:13 AM
ガイドラインには反してないと考える?
Avatar
ガは無理して正しい英語にしなくても…みたいなの書いてなかったっけ?
2:13 AM
それならまあうん
Avatar
omochimetaru 4/20/2017 2:14 AM
Name functions and methods according to their side-effects / Name Mutating/nonmutating method pairs には、変更して新しい値を返すやつは受け身系にしろ、みたいに書いてあるんだけど
2:15 AM
受身形は変更して新しい値を返すやつである、っていう逆方向は明言されてないからセーフ なんじゃないか
2:15 AM
と俺は思った。
Avatar
変更されたprを探してる、iPhoneでgithub漁るの難しい
2:15 AM
あった
2:16 AM
Added I brought up in the Slack channel that the original Disposable API .addDisposableTo(_ bag: DisposeBag) felt out of line with the newly minted Swift API guidelines. Because an Observable retur...
Avatar
@omochimetaru そこの文章ですけど
Avatar
slack見に行かないと議論の内容がわからないw
Avatar
mutating/non mutatingのペアの時にはそうしろって限定されてるんじゃないかと前@koherと話しました
Avatar
omochimetaru 4/20/2017 2:17 AM
@t.ae 片方しか無いなら命令形のまま新しいインスタンスを返しても良い?
2:17 AM
将来的な追加が予測できる以上結局ペアを想定しないといけない気がする (edited)
Avatar
そうですね
2:18 AM
disposed(by: )についてはペアがでてこなそうなのでこれで良い気もする。
2:18 AM
そもそもmutatingな何かじゃないし
Avatar
omochimetaru 4/20/2017 2:18 AM
そもそもこの話の枠外になるよね 同意見
Avatar
それはそれとして、Sequence.filterはどうするんやろ、ってずっと思ってる
2:20 AM
filtered?
Avatar
omochimetaru 4/20/2017 2:20 AM
なんかそこについては例外条項があるって @koher が言ってた
2:20 AM
filter みたいにあまりに有名なやつは特別
Avatar
例外、なるほど
Avatar
omochimetaru 4/20/2017 2:41 AM
うげ〜 SwiftのコードをObjCから見たら、 Error型がNSError型に見えてる
2:41 AM
URLがNSURLに見えるのとかは整合性取れるからいいけど、 ErrorとNSErrorはおかしくねえか・・・
Avatar
Error NSErrorウッ頭が
2:42 AM
全部NSErrorに変換できることになってるからまあわからんでもない
Avatar
ObjC互換のための暗黙的変換だったりするんですかね
Avatar
暗黙的変換(変換できるとは言っていない)ですね
2:43 AM
治ったのだろうか
2:44 AM
8.3.2で確認したけど修正されてるみたいだった
👏 1
2:46 AM
ErrorからNSErrorに強制的にキャストがかかる例のアレは未修正だった
2:46 AM
おこ
Avatar
norio_nomura 4/20/2017 3:10 AM
macOSとLinuxで結果が違った(tarunonさんの検証コード) import Foundation protocol MyCustomErrorProtocol: Error { var hoge: Int { get } } struct MyCustomError: MyCustomErrorProtocol { var hoge: Int { return 1 } } extension NSError: MyCustomErrorProtocol { var hoge: Int { return -1 } } let error: Error = MyCustomError() if let cError = error as? MyCustomErrorProtocol { print(cError.hoge) // macOS: -1, linux: 1 } (edited)
Avatar
omochimetaru 4/20/2017 3:18 AM
LinuxにはNSErrorが無い?
Avatar
norio_nomura 4/20/2017 3:22 AM
あるよ
3:22 AM
Objective-Cが無い
Avatar
omochimetaru 4/20/2017 3:23 AM
なるほど
Avatar
norio_nomura 4/20/2017 3:24 AM
NSErrorがSwiftで実装されてる。
Avatar
omochimetaru 4/20/2017 3:24 AM
ほ〜!
3:24 AM
いや、そりゃ当然の帰結としてそうか
Avatar
norio_nomura 4/20/2017 3:25 AM
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
Avatar
witness tableがいつ作られるのか気になって色々試してたら面白いのみつけた
Avatar
27行目は as Foo なのに FooStandardに準拠してることになってる?
Avatar
FooFatalが消えた
Avatar
それもそうだけど
Avatar
28?
Avatar
あ〜
Avatar
だから
10:59 AM
subclassが噛んだ瞬間にWitness tableが崩壊してるように見えている
Avatar
class Aの実装として extensionが動的に注入されてる?
Avatar
15行目で、より厳しい制約があるので、FooStandardがあるかは問題じゃないはずだが
Avatar
FooFatalのほうが無視されるのは
11:01 AM
静的な拡張としてしか扱われてないからなんじゃないかな
11:01 AM
これ1年前のtryswiftでたるのんが言ってたやつの仲間な気がする
11:01 AM
俺の予想だと
Avatar
それは思う
Avatar
class Aについては、Foo x FooStandardの組み合わせによって、 Aのメソッドとして
11:01 AM
fooが実装されてる
Avatar
てか、
Avatar
class Bについては、fooはオーバライドされてなくて
Avatar
struct B: Foo, FooStandard, FooFatalだと、コンパイルすら通らない
Avatar
FooFatalのwhere付きの静的な条件で、Bの型が見えてるときだけ
11:02 AM
静的ディスパッチでそっちが呼ばれる
Avatar
extensionで実装書くとwitness tableには関係しないのかなーと
Avatar
だから27行目も28行目もas Fooになった時点で、Foo型のexistanceとしてAやBのインスタンスがブリッジされてて
11:03 AM
Bの方はオーバーライドされたわけじゃないから、helloが出る
Avatar
FooStandardは探せるのに、FooFatalが探せてないのが気になる
Avatar
FooFatalは
11:04 AM
型がBとして確定したときしか
11:04 AM
見えない
11:04 AM
FooStandardは見つかってないんだけど
11:04 AM
Fooのfooとして読んでるだけで
11:04 AM
ただその実装がAにインストールされてる
11:04 AM
じゃないかなあ
Avatar
ふーむ
11:04 AM
struct B: Foo, FooStandard, FooFatal {} こっちはコンパイル通らないし
11:04 AM
それはそれとしてなんか普通に壊れてる気がする
Avatar
それだと、FooStandardとFooFatalの両方見つかる結果
11:05 AM
extensionが両方みつかって
Avatar
いやいや
11:05 AM
厳しい方優先すればいいでしょ
Avatar
どっちの実装をぶち込むか決められないんじゃない?
Avatar
extension Foo where Self: FooStandard vs extension Foo where Self: FooFatal
11:05 AM
これならどっち優先かわからない
Avatar
25行目のケースでfatalが出るってことは、
Avatar
あ、ごめん
11:06 AM
privateついてるせいだった
Avatar
厳しい方が優先っていうルール自体は存在してるのか
Avatar
FooFatalにprivateあるせいで
11:07 AM
要らんエラー履いてた
Avatar
a~
Avatar
Structは通った
Avatar
このprivate見てなかった
11:07 AM
てか、private protocol、この前も出てきたけど意味がよくわかってない
11:07 AM
何がprivateになるの
Avatar
ファイルの中でしか使えなくなる
Avatar
ファイルなんだ。
Avatar
一番外側のprivateはfileprivateと一緒
👌 1
11:08 AM
てか
11:08 AM
class Bにprivate protocol生やしても動くのは
11:08 AM
あー見えなくてもいいからか
Avatar
FooFatalをprivateではなくしても
11:13 AM
結果は同じだなあ
11:15 AM
sil_witness_table hidden AAA: Foo module a { method #Foo.foo!1: @_TTWC1a3AAAS_3FooS_FS1_3foofT_SS // protocol witness for Foo.foo() -> String in conformance AAA }
Avatar
作られてない?
11:17 AM
なんとなくそんな気はしたけど
Avatar
AAAのFoo conformanceが↑のテーブルで、fooメソッドとして _TTWC1a3AAAS_3FooS_FS1_3foofT_SS が入ってて それが内部で、 _TFe1aRxS_3FooxS_11FooStandardrS0_3foofT_SS を呼ぶようになってる
11:18 AM
_TFe1aRxS_3FooxS_11FooStandardrS0_3foofT_SS は、 A が // Foo<A where ...>.foo() -> String のwhereを満たしてる時ようのメソッド
11:19 AM
sil_vtable AAA { #AAA.deinit!deallocator: _TFC1a3AAAD // AAA.__deallocating_deinit #AAA.init!initializer.1: _TFC1a3AAAcfT_S0_ // AAA.init() -> AAA } sil_vtable BBB { #AAA.init!initializer.1: _TFC1a3BBBcfT_S0_ // BBB.init() -> BBB #BBB.deinit!deallocator: _TFC1a3BBBD // BBB.__deallocating_deinit }
11:19 AM
AとB自体はメソッドとしては保持してなかった。
11:19 AM
あくまでAがFooとしてアップキャストされるとき用のwitness-tableにfooの実装として hello の実装が入ってる
11:20 AM
FooFatalの方のwitnessは無さそう
11:20 AM
BがFooになるときは、親のAと同じ挙動でFooのExistanceになるっぽい
😳 1
11:21 AM
(FooFatalのprivateは外した状態で試した。わかりやすいようにAAAとBBBにリネームした。
Avatar
やっぱりsubclass絡んだwitness tableは暗黒界だ
Avatar
親クラスが満たすプロトコルとしてのExistanceはサブクラス側では作られないってことじゃないかな
11:22 AM
sil_witness_table hidden AAA: Foo module a { method #Foo.foo!1: @_TTWC1a3AAAS_3FooS_FS1_3foofT_SS // protocol witness for Foo.foo() -> String in conformance AAA } sil_witness_table hidden AAA: FooStandard module a { } sil_witness_table hidden BBB: FooFatal module a { }
11:22 AM
AAAのFooStandard witnessはあるけど、BBBのFooStandardはない
11:22 AM
一方BBBのFooFatalはある
Avatar
むむむむ
Avatar
割りと一貫したルールな気がする
11:23 AM
「あるクラスが定義される時、それが満たすプロトコル全てに対してwitness-tableを作るが、 例外として、親クラスで既にそのプロトコルについてのwitness-tableが作られているときは、作られない」
11:25 AM
1年前のやつは、その時に、クラス側にもメソッド定義があれば、それがvtableエントリに入ってきて、オーバーライドが働くっていうケースも混ざってた
11:26 AM
try-swiftで知り合った @tarunon さんから面白い話を伺いました。 以下、Xcode 7.2.1 (7C1002)の環境での話です。

結論

どうしたらいいかわかりません。。

本題

下記のように、 エクス...
11:26 AM
↑当時のまとめ
Avatar
これ確かバグ報告出した奴だっけか
11:27 AM
なんかこの辺無限に見つけてて、どれがどれかわからん
11:28 AM
これは仕様っぽかったからスルーしたんだ
11:28 AM
ちょいまっち
11:29 AM
アトラシアン💢iPhoneから全く操作できない💢💢💢
Avatar
てか、仕様が明文化されてないから
11:31 AM
コンパイラクラッシュ以外は
Avatar
ああ、これのうち、後ろ2つについて報告したんだ
11:31 AM
親クラスの宣言の有無で切り替わる奴
Avatar
実装が仕様なんじゃね
Avatar
実装が仕様w
Avatar
お返事あった?
Avatar
なんかワイワイやってるっぽい
11:34 AM
Doug Gregor氏がこれはバグだろうけど破壊的変更だからevolutionに乗せないとなみたいなこと書いてる気がする
Avatar
ほんとだ
11:35 AM
エボリューションプロセスで整理するって流れっぽい?
Avatar
最後の書き込みが、「やるけど明日からバカンスだぜ」(悪意のある翻訳)に見える
11:37 AM
4でprotocol周りやるからこれと向き合わないと死体増えそうな気がするけど大丈夫なのかな
Avatar
クラスに関しては open にしない限りサブクラス系の問題はモジュール内で解決できちゃうし、基本 open はよっぽどの理由が無い限り使わないように、ってことになってるので、プライオリティは低い気がしますねぇ。
Avatar
継承周りはおざなりな感じありますね
Avatar
今日 master から 4.0 への無条件マージの期限が 6/1 に切られたので、それ以降に source breaking な変更が4.0に入ることはなさそう。
Avatar
ふむふむ
Avatar
あと1ヶ月ちょいってこと考えると、厳しいと思います。
Avatar
やるなら手前でやるしかないかぁ、6月1日は無理ぽ
Avatar
結局iOSでコード書くと、classと継承は避けては通れないので
11:47 AM
この手の挙動とどう折り合いを付けていってるのか凄い気になる
Avatar
Swiftが最も使われてるのは間違いなくiOSアプリ開発だけど、SwiftはiOSを重要視してない感があるなぁ。値型中心の世界を作ろうとしてるし、SwiftPMはiOSサポートしてないし。
Avatar
まだ見れてないままだけど↓とか気になってる。 https://developer.apple.com/videos/play/wwdc2016/419/
Avatar
-emit-irを使うとメソッドにどのwitness tableが渡されてるかわかるぽい。 callFoo(B()) // hello %112 = call { i64, i64, i64 } @main.callFoo <A where A: main.Foo> (A) -> Swift.String(%swift.opaque* noalias nocapture %111, %swift.type* %21, i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @protocol witness table for main.A : main.Foo in main, i32 0, i32 0)) class C: Foo, FooStandard, FooFatal {} callFoo(C()) // fatal %122 = call { i64, i64, i64 } @main.callFoo <A where A: main.Foo> (A) -> Swift.String(%swift.opaque* noalias nocapture %121, %swift.type* %118, i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @protocol witness table for main.C : main.Foo in main, i32 0, i32 0)) (edited)
Avatar
norio_nomura 4/21/2017 1:52 AM
Swift 4.0のCHANGELOGにこんなのが https://github.com/apple/swift/blob/master/CHANGELOG.md
SR-1529: Covariant method overrides are now fully supported, fixing many crashes and compile-time assertions when defining or calling such methods. Examples:
class Bed {} class Nook : Bed {} class Cat<T> { func eat(snack: T) {} func play(game: String) {} func sleep(where: Nook) {} } class Dog : Cat<(Int, Int)> { // 'T' becomes concrete override func eat(snack: (Int, Int)) {} // 'game' becomes optional override func play(game: String?) {} // 'where' becomes a superclass override func sleep(where: Bed) {} }
(edited)
swift - The Swift Programming Language
Avatar
↑今でも問題なくコンパイルも実行もできる気がします・・・
Avatar
omochimetaru 4/21/2017 2:46 AM
なんかこれおかしくないか?
2:46 AM
Dog is Catだから、 DogのインスタンスはCatとして振る舞えなきゃいけなくて
2:46 AM
CatはsleepメソッドでNookを受け取る (edited)
2:46 AM
DogはSleepメソッドをオーバーライドしてるけど
Avatar
問題ないでしょ?
2:47 AM
引数については contravariant だから。
2:47 AM
より広い値を受ける分には問題ない。
Avatar
omochimetaru 4/21/2017 2:47 AM
せまいですよ
2:47 AM
ああぎゃくか
2:47 AM
親のほうが広いのか
Avatar
それにしても Dog: Cat ってカオスw
Avatar
omochimetaru 4/21/2017 2:47 AM
じゃあ、playがおかしくない?
2:47 AM
いや、これはいいな
Avatar
String? の方が広い。
Avatar
omochimetaru 4/21/2017 2:48 AM
いいのか。Nook < Bed で STring < String?か
Avatar
うん。
Avatar
omochimetaru 4/21/2017 2:49 AM
引数のオーバーライドがちゃんとcontravariantならJavaより正しいな
2:49 AM
でも、広くするってことは
Avatar
これを " Covariant method overrides" っていうのは正式な用語なのかな? Contra な引数に広いものを渡すのは - * - = + で Covariant ってこと?
Avatar
omochimetaru 4/21/2017 2:49 AM
親で func foo(cat: Cat) と func foo(dog: Dog) のとき
2:49 AM
サブで func foo(animal: Animal) としたら
2:49 AM
Cat < Animal と広げたのか Dog < Animalと広げたのか
2:50 AM
曖昧になりそう。両方を同時にオーバーライド?
Avatar
↑Swiftならラベルで区別されちゃうw
Avatar
omochimetaru 4/21/2017 2:50 AM
あ〜そっか。
Avatar
ラベルも同じだったらどうなるんだろ。
Avatar
omochimetaru 4/21/2017 2:50 AM
じゃあ ラベル省略されてるとき。
2:50 AM
その場合はエラーでもまあ
2:50 AM
概ねラベルで分離できるなら困りはしないな
Avatar
オーバーロードがあるとそこややこしいんだよね。
2:51 AM
Java だとオーバーライドで引数を広げようとしたらオーバーロードになるんだっけ?
Avatar
norio_nomura 4/21/2017 3:23 AM
元のissueのコードを試すと確かにクラッシュする。 https://bugs.swift.org/browse/SR-1529
Avatar
norio_nomura 4/21/2017 3:33 AM
import Cocoa class CrasherBase: NSView { var hasRect: Bool = false var rect: CGRect? { return hasRect ? CGRect(x: 0, y: 0, width: 50, height: 50) : nil } override func draw(_ dirtyRect: NSRect) { NSEraseRect(dirtyRect) } } class Crasher2: CrasherBase { override var rect: CGRect { return CGRect(x: 0, y: 0, width: 100, height: 100) } override func draw(_ dirtyRect: NSRect) { NSEraseRect(rect) } }
Avatar
ほんとだ。クラッシュしました。
4:08 AM
あれ?↓はいける。 class Animal { var foo: Int? { return nil } } class Cat: Animal { override var foo: Int { return 42 } } (edited)
Avatar
引数の反変だとoverrideでうまく動くけど返り値の共変だと死ぬのかな
4:09 AM
あー
4:09 AM
setterがあるからそんな単純な話じゃなかった
Avatar
なんで↑はクラッシュしないんだ??
Avatar
そもそも@norio_nomuraさんが貼ったコードの Crasher2#drawを消したらクラッシュしないんですが
4:16 AM
いやゲッタ呼び出し段階の話かな?
Avatar
norio_nomura 4/21/2017 4:16 AM
NSEraseRect(rect) がミソですね
Avatar
ああ、
4:19 AM
たぶん@koherと同じ勘違いしてましたね
Avatar
あー、そっちなのか。
4:22 AM
↓死んだ。 class Animal { var foo: Int? { return nil } } class Cat: Animal { override var foo: Int { return 42 } func useFoo() -> Int { return self.foo * 2 } }
4:25 AM
func でもダメだ。 class Animal { func foo() -> Int? { return nil } } class Cat: Animal { override func foo() -> Int { return 42 } func useFoo() -> Int { return self.foo() * 2 } } (edited)
Avatar
class Animal { func foo() -> Int? { return nil } } class Cat: Animal { override func foo() -> Int { return 42 } } Cat().foo() * 2 ↑外で呼んでもダメですね
4:28 AM
そもそもfooの呼び出しがどうやっても死ぬ
Avatar
あー、確かに昔 Optional とサブタイピングについて調べてたときに踏んだ気がする。継承で戻り値狭められるから FooFoo? のサブタイプ扱いされてますねって話で、でもメソッド定義するだけじゃなくて使おうとしたらすぐ死んでた気が。
Avatar
class Animal { func foo() -> Int? { return nil } } class Cat: Animal { override func foo() -> Int { return 42 } } let f = Cat().foo f() ↑回避できた
Avatar
Cat.foo(f)()だと行けるかと思ったけど死んだ
Avatar
@tarunon さんはよく FooFoo? に暗黙の型変換されるのを邪悪だと言ってますが、オーバーライドで戻り値を Foo? から Foo に狭められるなら FooFoo? のサブタイプでないといけないわけで、それなら Foo? 型変数に Foo を代入するのは暗黙の型変換ではなくアップキャストとみなせるわけですが、それについてはどうですか?
Avatar
うーん、このオーバーライド自体邪悪っぽい気がしていて
4:32 AM
いや、ダメでしょ…という感じがする
Avatar
FooFoo? のサブタイピング自体が邪悪ってことですね。
Avatar
そうです
Avatar
そうなんですよねぇ・・・
4:33 AM
Swift の Optional は Tagged Union なんだから本来サブタイプじゃないはずなんですけど、サブタイプ的にに振る舞わせることで、 Untagged Union で作られた Optional みたいになっちゃってるんですよね。
Avatar
Nullセーフになったのはまあそうなんですが
Avatar
Ceylon とかだと Foo?Foo|Null という (Untagged) Union になってて、当然 FooFoo?` のサブタイプなんですけど、
Avatar
Optionalセーフ?(と言って良いのかわからないけど)の域にはたどり着けない感
Avatar
Swift は Tagged Union だから Foo?? とかもできるわけだし、サブタイプ的に振る舞わせるのが微妙ですよねぇ・・・。
4:35 AM
だから、オーバーライドで Foo?Foo に狭めるのも、代入時の暗黙の型変換も全部なしってのがシンプルな気がする。今更無理だけど。
Avatar
omochimetaru 4/21/2017 4:35 AM
それだなあ。 TaggedUnionだとおかしくなる
Avatar
SwiftのOptionalに関しては、この暗黙のサブタイピングと
4:35 AM
ぶっちゃけSimpleDomainErrorも、それ単体でErrorが解ればいい、でOptionalにしがちだけど、 プログラムって必ず組み合わせて使うんだから単体では単純で良くても組み合わせたときのことを考慮するとErrorを吐くのが妥当、だよなぁ、って。 #swtws
4:35 AM
ここからの一連の議論の内容
4:36 AM
そこさえなんとかなれば
4:36 AM
Optionalを使うことに関して、変に気を使う必要が全くなくなる美しい世界が来ると考えていて
4:36 AM
遥か遠い理想郷
Avatar
omochimetaru 4/21/2017 4:36 AM
C++でOptional自作して使ってるけど、 毎回 Some(x) で包むので特に不便感じない
Avatar
あ、そうだ。それなんですけど、書こうと思ってて忘れてました。 Twitter に書いた方が後から見やすいかもですが、 SimpleDomainErrorthrows じゃダメな理由がわかりました。
4:37 AM
純粋な値がない Optional と Simple domain error が区別されることも意味がありますが、 Simple domain error が Recoverable error と区別されることにも意味がありそうです。
4:37 AM
なぜなら、
4:38 AM
struct SimpleDomainError: Error {} は、当然ですが Simple domain error なので、エラーが発生したという情報しか持たないわけです。
Avatar
全ての型で同じSDE型使ったらカオスにしかならないですが、そこはextension Int { struct SDE: Error {}} とか (edited)
4:40 AM
最低でも何の型でのSDEなのかは区別するべきでは
Avatar
しかし、 throws というのはエラーを合成したり伝播したりして処理するために設計されているんで (edited)
Avatar
RecoverableErrorとの混同より、Optionalとの混同のほうが
4:41 AM
煩雑さが増しますよ、経験則ですが
Avatar
Simple domain error を Error にしてしまうとそういう風に使うことをミスリードしてしまうわけです。
4:44 AM
Simple domain error はエラー情報を持たないためにすぐに処理しないとわけがわからなくなってしまうので
Avatar
であればFatalがそもそも正しいのでは、という気がする
Avatar
Error のまま取り回したり合成したりすることを推奨するのは望ましくないと。
Avatar
Optionalを扱うことにベストプラクティスを議論しなくていい世界観があるはずで、そこに到れるはず
4:45 AM
今日Intのベストプラクティスを議論する人が居ないのと同じように
Avatar
なので、値がないことと Simple domain error を区別するためには、 enum Failable<Value> { case success(Value) case failure }Optional とは別に作るのがいいかもしれません。
Avatar
throw SDE optionalで型分けるんですね
Avatar
はい
Avatar
SDEとRecoverableErrorの区別を、普遍的に人が理解できるところまで到達できれば
4:47 AM
いけそう
4:47 AM
人類進化してくれ
Avatar
ただ、個人的には複雑すぎる気がするし、値がないこととオペレーションの失敗を区別できないこともある気がするので( array.first とか dictionary[foo] とか)
Avatar
紛らわしいのはオーバーロードするなりして欲しいんですよね
4:48 AM
利用者側で決定付けれるはず
4:48 AM
なので
Avatar
ErrorOptional のどっちに寄せるかと言われると、個人的にはすぐ処理することが強制される Optional かなぁと思います。
Avatar
SDEが情報を持ってないのが前提なのも良くない気がしていて
4:49 AM
Error型がそもそも、デバッグ時には発生時のコールスタック持てるとか
4:49 AM
そういう機能を有していれば、まあそれはそれで解決できると思うんですよね
Avatar
Simple domain error を一切作らずに、すべてエラー情報を持った Error にするという世界もあり得るとは思います。 (edited)
Avatar
僕の理想としては、
Simple domain error を一切作らずに、すべてエラー情報を持った Error にするという世界もあり得るとは思います。
これが一番近い
Avatar
値がないかもしれない Optional か、 Error で表す Recoverable error か。
4:51 AM
ただ、 array.first とか array.max とかを Optional にするなら、それで消せるのって Int.init(String) くらいな気もするんですよね。
4:51 AM
純粋な Simple domain error ってほとんどない気がするから・・・。
Avatar
Int8(Int64)とかも
4:51 AM
まあ結構ありますよ
Avatar
まあ、変換系ですよね。
4:51 AM
conversion の失敗くらい?
Avatar
すぐ処理することが強制される Optional
4:52 AM
これがイマイチわからない
4:53 AM
Optionalは別にすぐに処理することを強制してないですよ
Avatar
プロパティに保持するのはいいですが、
4:53 AM
複数の Optional を合成しちゃうと出処がわからなくなって
Avatar
出処がわからなくなったら困る状況になってるのが後手ではないですか?
Avatar
デバッグするときに nil じゃないはずの値が nil になっちゃったときに、どれが元々 nil なんだ?ってのを探るのが大変
Avatar
前も書きましたが、複数のIntを合成して、偶数になるはずが奇数になったのでどれが奇数だったかわからなくて困る
4:54 AM
本質的にはこれと一緒の事を議論している気がしていて
4:55 AM
実際にはそれとは差がある、その差を生んでるのがロジックエラーの混入なわけです
Avatar
複数の Int を足して偶数を期待する状況は稀にしかおこりませんが、
4:55 AM
nil だと起こると思うんですよ。
4:55 AM
たとえば SwiftyJSON を使って JSON をデコードすると
4:56 AM
return curry(User.init) <^> json["name"] <*> json["age"] <*> json["gender"]
4:56 AM
みたいなコードを書いて、結果が nil だった場合にどのパラメータが nil だったんだ?みたいな。
Avatar
それはErrorにするべきものをOptionalにしてるだけでは
4:57 AM
Himotokiはキーパス毎にErrorが出ます、なので困らない
Avatar
でも本質的には同じじゃないですか?
Avatar
いや、だからOptionalにErrorを混ぜると
4:57 AM
そういう問題が起こるんです
Avatar
name: String?age: Int?gender: Gender? があるときに
4:58 AM
それが別に SImple domain error じゃなくて
4:58 AM
別の Optional プロパティからとってきたときかもしれないですよね?
4:58 AM
DB 上任意項目の name, age, gender があって
4:58 AM
そのレコードから取得してるかもしれない
Avatar
発生場所がバラバラなら、発生場所毎にデコード処理なりなんなりあるわけで
Avatar
struct UserRecord { var name: String? var age: Int? var gender: Int? }
Avatar
そこできっちりErrorを生成すればいい
4:59 AM
そもそもUserRecordのそれらの値が
4:59 AM
クライアントサイドの型的にもOptionalが許容されているなら
4:59 AM
合成で問題が起こるはずがない
Avatar
とか、 jsonjson じゃなくて record という Dictionary かも。
5:00 AM
いや、なので本来的には
5:01 AM
guard let name = record["name"] else { throw ... } guard let age = record["age"] else { throw } guard let gender = record["gender"] else { throw } return User(name, age, gender) (edited)
5:01 AM
とすべきだということです。
Avatar
うーん
Avatar
これが Optional をすぐに処理すべきという話。
Avatar
例えばDictionaryの添字アクセスがErrorだったら
5:01 AM
その辺がもう少し書きやすくなるんで
5:01 AM
まあオーバーロードで、用途によってですね
5:02 AM
適切に使えたほうが良いなあということです
Avatar
オーバーロードでというのは、↓みたいなのがほしいということですか? extension Dictionary { subscript(key: Key) throws -> Value { ... } }
Avatar
ですです、
5:05 AM
do { return try User(record["name"], record["age"], record["gender"]) } catch { throw User.Error.decodeFail(error) } (edited)
5:05 AM
こうなりますよね
5:05 AM
スッとする
5:05 AM
tryがある時にErrorになってくれて、それ以外はOptionalみたいな
5:06 AM
まあそういう機能があって、この微妙な境界線をですね
5:06 AM
サーッと解決してくれたら嬉しいなって
5:06 AM
そういう話です
Avatar
そもそもUserRecordのそれらの値が クライアントサイドの型的にもOptionalが許容されているなら 合成で問題が起こるはずがない
これはそうとも言えなくて、アプリ全体では User 各プロパティに nil が許されているけど、特定の機能に関してはすべて非 Optional なプロパティをもった CompleteUser が求められているかもしれないです。そういうときに User から CompleteUser を作るのも同じ話になります。
5:07 AM
僕がすぐ処理すべきと言っているのは値がない意味でプロパティに持つなということではなくて
5:07 AM
それを使う側の関数のローカルスコープで長々と保持するなということですね。
Avatar
うーん
5:08 AM
まあOptionalから値取り出して使うならそうなんですが
Avatar
逆に Optional をローカルで取り回したいケースってどういうときがありますか?
Avatar
OptionalはOptionalとして使うから
5:09 AM
普通にNullableなモデルとして使いませんか?
Avatar
プロパティを nullable にするのはわかりますが、関数ローカルで nullable なまま取り回さないといけないケースって稀だと思うんですよね。
5:11 AM
もしその nullable を合成しちゃったら結局出処がわからない問題になっちゃうし
5:11 AM
合成しないならどうぜ後で処理しなきゃいけないからすぐに処理すればいいし。 (edited)
5:14 AM
Optional な引数に渡す値を作って、可読性のために一度変数に代入したいときとか?
Avatar
omochimetaru 4/21/2017 5:15 AM
ヌルのまま取り回していいのは
5:15 AM
合成結果が意味的にヌルで正しい場合だけで
5:15 AM
途中で出てくる
5:16 AM
その文脈においてエラーであるはずのほうの
5:16 AM
ヌルを混ぜちゃいけない
Avatar
合成結果が意味的にヌルで正しい場合
っていうのは、それを Optional としてそのまま使いたい場合、つまり、何かの引数に渡したい場合ってことであってる?
Avatar
omochimetaru 4/21/2017 5:17 AM
と思う
Avatar
です
Avatar
omochimetaru 4/21/2017 5:17 AM
どういうケースがあるかなあ たとえば、ユーザーがペットを持ってる時に
Avatar
えっと、 Simple domain error の話はとりあえずおいておいて、たとえ「値がない」という意味の Optional であったとしても関数ローカルではすぐにハンドリングすべきというのが僕の考えで
Avatar
omochimetaru 4/21/2017 5:18 AM
ペット?を渡す関数に
5:18 AM
ユーザーがヌルの時もペットがヌルとしちゃっていい場合(表示とか
5:18 AM
まあこれは合成といっても?.で済むけど
Avatar
@omochimetaru つまり、やっぱり引数に渡す場合ってことやんね?
Avatar
omochimetaru 4/21/2017 5:19 AM
たしかに?
5:19 AM
何かの引数に渡さない事ってあるか?
Avatar
引数に渡す場合はあり得ると思う。
5:19 AM
nil かどうかで分岐して何か処理する場合。 < 引数に渡さない場合 (edited)
Avatar
omochimetaru 4/21/2017 5:19 AM
なるほど
5:20 AM
確かにそのような分岐を含んだ関数を定義する意味は無さそうだから呼び出し前の分岐になる
Avatar
普通に、ユーザデータが全部入力されて、そしたらButtonが押せるようになるとかも
5:20 AM
Optionalの合成ですが特に何も考えなくて良い例ですね
Avatar
分岐の中にはエラーを発生させるというのもあって、たとえ「値がないかもしれない」 Optional であったとしても、その値が nil の状態で実行するとその処理としてはエラーとして Errorthrow するとかはあり得る。
Avatar
でもこの場合は入力されてないのはErrorとして扱いたいな
5:22 AM
Validationに食わせる時にErrorになるか
Avatar
普通に、ユーザデータが全部入力されて、そしたらButtonが押せるようになるとかも Optionalの合成ですが特に何も考えなくて良い例ですね
このまえのベストプラクティスに書いたとおり、 Optional の合成は必ずしも悪ではないと考えていますが、それにしてもその合成結果を長々と取り回す必要はなくて、 N 個の Optional を合成後すぐに処理すべきですよね?
Avatar
これはそうですね、実際にはValidationでErrorが生成されているので
5:23 AM
T?ではなくT|Errorだ
5:24 AM
本質的にはその定義が良いが、UIKitのせいでT?になってるか
Avatar
そう考えると、合成した場合でもすぐに処理をしたいわけで、引数に渡す目的で Optional 値を生成するという以外に、 Optional のまま値を取り回したいケースってないような気がするんですよね。
5:28 AM
引数に渡す場合でも、一度作っちゃえば後はそれを渡す以外に使わないから、他のコードとは独立してるし。
Avatar
omochimetaru 4/21/2017 5:30 AM
たとえば
Avatar
最悪なのは↓みたいなコード let foo: Foo? = ... ... let bar: Bar? = foo?.bar(...) ... let baz: Baz? = a.b?.c.flatMap { bar?.baz($0) } ... guard let qux = baz.map { Qux($0) } else { ... }
Avatar
omochimetaru 4/21/2017 5:30 AM
var onComplete: (()->Void))?
5:30 AM
みたいなプロパティは
5:30 AM
必要だと思うけど、 これは、 取り回す場合かつ関数に渡さない場合
5:30 AM
じゃないですか?
Avatar
今話してるのはプロパティの話ではなくて、関数やメソッドローカルの話。
5:31 AM
プロパティの「値がないかもしれない」ことを表すために Optional を使うのは当然あり得ると思います。
Avatar
omochimetaru 4/21/2017 5:32 AM
なるほど
Avatar
うーん
5:32 AM
だから、僕の一番最初に言っていたのは
5:32 AM
プロパティの「値がないかもしれない」ことを表すために Optional を使う
5:32 AM
これが本来的な使い方のはずで、それ以外をOptionalで表現されている現状
5:32 AM
ベストプラクティスを議論せざるを得ない、ということになっている
5:33 AM
っていうところですかね
5:33 AM
プロパティの値がないかもしれないを合成した結果、値がないかもしれないは当たり前で
5:33 AM
別にどれが原因だーなんて気にしなくても良いことが多いので
5:33 AM
Errorメッセージ出してくれという要求があってチェックすることはまああるっちゃあるけど
Avatar
omochimetaru 4/21/2017 5:33 AM
@tarunon 文字列の中から文字を探して、見つかればそのindexを返す関数は、返り値はオプショナル?
Avatar
それは意図によるのでは
5:34 AM
あるかもしれない、ならOptionalだし、なければおかしい、ならErrorであるべき
Avatar
omochimetaru 4/21/2017 5:34 AM
じゃあ
5:34 AM
自分がそういう関数を使いたい時
5:34 AM
どっちが用意されていてほしい?
Avatar
オーバーロードが理想
5:34 AM
それは上にも書いてある
Avatar
omochimetaru 4/21/2017 5:34 AM
どちらかを用意して簡易に変換するのは駄目?
Avatar
tryを書けばErrorが出てきて、書かなければOptionalになるみたいな
5:35 AM
用意して変換するならErrorしかない、try?がある以上その選択になるのでは。
Avatar
omochimetaru 4/21/2017 5:35 AM
なるほど。
Avatar
ただそれは面倒臭すぎるし、Error周りはまだ貧弱だから
5:35 AM
今はOptionalに打ち込まれてる、まあそれはしゃーない
Avatar
omochimetaru 4/21/2017 5:35 AM
いまはtry?による変換もめんどくさいよね 左に書くのが嫌だわ
Avatar
そうなんだよなー
Avatar
うん、それはある。
5:36 AM
try(相当のもの) は右にあるべきだった。 (edited)
Avatar
omochimetaru 4/21/2017 5:36 AM
なるほどなあ
Avatar
記号がですね
5:36 AM
implicitly unwrapに!を使ってしまったので
Avatar
omochimetaru 4/21/2017 5:36 AM
わり同意見だなあ
Avatar
try相当が!だったら……
Avatar
それをいうと Int.init(String) とかも面倒で、 string.toInt() みたいに右にある方が使いやすかった。
Avatar
omochimetaru 4/21/2017 5:37 AM
そもそものSDEの話は考え中
Avatar
string => { Int($0) } ですかね・・・。 (edited)
Avatar
omochimetaru 4/21/2017 5:38 AM
エラーがあったことしかわからないエラー っていう概念を前提に考えればコヒーの意見はわかるけど、 それがそもそもおかしい気がする
Avatar
うん、それがおかしいという意見もありえて、 Int.init(String) 等の conversion 系は throws であるべきというのはあり得る。
5:41 AM
一方で、↑の index とか、 first, minDictionary.subscript がエラーなのかどうかは解釈次第だと思う。 @tarunon さんの言うようにオーバーロードも一つの解なのかもしれないけど、それを正しく使い分けられる人は少なそう・・・。
Avatar
そもそもGenericsすら使いこなせない人もいるから
Avatar
omochimetaru 4/21/2017 5:41 AM
でもそういう解釈を記述できる方が
Avatar
まあそれはそれ、使える人にフォーカスしていいとは思う
Avatar
omochimetaru 4/21/2017 5:41 AM
書ける人にとっては
5:41 AM
より安全で読みやすく
5:41 AM
できてよいよね
Avatar
Optional to throws の簡単な方法があればいいんじゃないかな? (edited)
Avatar
omochimetaru 4/21/2017 5:42 AM
変換の失敗系は、与えられた入力と、 なにからなにへの変換が失敗したのか という情報をもっててほしいなー
Avatar
Anyを書いたらコードレビューで殴るように、不適切にOptionalをオーバーロードしたらレビューで殴る
5:42 AM
それができれば僕は満足かな
Avatar
omochimetaru 4/21/2017 5:43 AM
Resultのdematerializeみたいな?
Avatar
前に Erica さんが swift-evolution で Optional 用の ??? 演算子を提案してて
Avatar
omochimetaru 4/21/2017 5:43 AM
あーなんかそれ俺も似たメール読んだ
Avatar
結局 guard でいいでしょということで終わった。
Avatar
omochimetaru 4/21/2017 5:43 AM
!!と二個ビックリだと例外
5:44 AM
後置ビックリね
Avatar
いやー、 !!! より危なそうに見えるから
Avatar
norio_nomura 4/21/2017 5:44 AM
func f() -> String? { return "Optional<String>" } func f() throws -> String { return "String" } let a = try? f() // "String" let b: String? = f() // "Optional<String>" // ^ 型アノテーションがないと error: ambiguous use of 'f()'
Avatar
omochimetaru 4/21/2017 5:45 AM
オプショナル版はfOrNil()でどうか
Avatar
Recoverable なエラーの throws に対して Logic failure 無視の ! より危険そうな !! を割り当てるのは微妙そう。
Avatar
omochimetaru 4/21/2017 5:45 AM
じゃあ!と!!を入れ替えよう
5:45 AM
いまさらンゴね
Avatar
我々が使える記号がたかだか10個前後くらいしかないのが問題
Avatar
norio_nomura 4/21/2017 5:48 AM
オーバーロードは微妙に思える。
Avatar
omochimetaru 4/21/2017 5:49 AM
のむらさん、もしかしてそれ、
5:49 AM
トップレベルだから
5:49 AM
throws空間の中にいるのが
5:49 AM
関係してますかね?
5:50 AM
throwsが付いてない関数の中からの呼び出しなら
5:50 AM
かわったりする?
Avatar
@omochimetaru それでも try は書かないといけないから同じじゃないかな?
Avatar
omochimetaru 4/21/2017 5:50 AM
あー
Avatar
norio_nomura 4/21/2017 5:51 AM
@koher ああ確かに。トップレベルでしか成り立たない。
Avatar
今は言語レベルでサポートされてないから
5:52 AM
class C { func s() throws -> String { return "a" } func s() -> String? { return "b" } } do { let a: String = try C().s() // a let b: String? = C().s() // b } catch { print(error) }
5:52 AM
まあこうなっちゃいますね、どちらも型明記しないとコンパイルエラー
5:53 AM
オーバーロードは言語サポートが乗った上でのifの話です
Avatar
norio_nomura 4/21/2017 5:53 AM
struct S { func f() -> String? { return "Optional<String>" } func f() throws -> String { return "String" } func nonThrow() { let a = try? f() // "String" let b: String? = f() // "Optional<String>" // ^ 型アノテーションがないと error: ambiguous use of 'f()' } } (edited)
Avatar
そもそもこの場合
5:54 AM
オーバーロードしてるString?はtry?した場合と同じ結果で良いので
5:56 AM
構文とセットで用意されれば理想っぽい
Avatar
うーん、片方から片方に簡単に変換できるのがいい気がする。
5:57 AM
やっぱ ??? があればよかったのかなぁ。
Avatar
omochimetaru 4/21/2017 5:57 AM
情報が減る方向しかないからエラーからOptionalが良さそう
5:57 AM
何も情報がないSDEを受け入れるなら逆も可能だが
Avatar
そうなんだけど、 array.first とかが throws なのはきつい気も。
Avatar
omochimetaru 4/21/2017 5:58 AM
そうかなあ、そうでもないんじゃないかなあ。
Avatar
あー、あと今の Swift 的な話なら、プロパティだと throws にできない問題が。
Avatar
Avatar
omochimetaru 4/21/2017 5:58 AM
むしろそれは良い気がする
Avatar
これらの議論は、Error周りの進化が前提ですよ
Avatar
omochimetaru 4/21/2017 5:58 AM
プロパティは失敗しないべき
Avatar
僕としては
Avatar
いや、 first はプロパティなので
5:59 AM
とすると
Avatar
omochimetaru 4/21/2017 5:59 AM
get/setが同じ型でいったりきたりできる、変数みたいな特性で。
5:59 AM
あ〜〜〜〜〜〜
Avatar
プロパティ版は Optional
5:59 AM
メソッド版は throws とか?
5:59 AM
そんなオーバーロードできんだっけ?
Avatar
omochimetaru 4/21/2017 5:59 AM
プロパティも完全に関数のように修正するのがいいのか
6:00 AM
失敗するfirstは関数に変えるのがいいのか
6:00 AM
なやましい
Avatar
いや、余計曖昧になる? array.firstfirst() のメソッドリファレンスかもしれない・・・
Avatar
それがあり得るので今は動かないと思います
Avatar
最初の要素という意味で first というプロパティがあって、最初の値がないから nil ってのはごく自然な解釈だとも思うんだよなぁ。
Avatar
omochimetaru 4/21/2017 6:02 AM
今まではそう思ってたけど最近はトンチの濫用って感じの気持ち
6:03 AM
無いものは取れない
6:03 AM
「無を取得」を思い出した
Avatar
それって stored な Optional プロパティも否定してない? < 無いものは取れない (edited)
Avatar
「問題ありません」
Avatar
omochimetaru 4/21/2017 6:04 AM
それはnilがちゃんと書き込まれてるから
Avatar
あー
Avatar
omochimetaru 4/21/2017 6:04 AM
なんていうのかな
6:04 AM
Arrayに firstっていうフィールドがあるわけじゃない
6:04 AM
nilをストアできているのと
Avatar
亜空間から.noneを生成してるということ
Avatar
omochimetaru 4/21/2017 6:04 AM
擬似的にnilが空間に出現するのが
6:04 AM
違う感じがする
6:04 AM
そうそう!
Avatar
それはカプセル化された内部表現の話じゃないかなぁ。 < フィールドがあるわけじゃない
Avatar
omochimetaru 4/21/2017 6:05 AM
でも、メンタルモデルとしても
6:05 AM
最初の要素という意味で first というプロパティがあって、最初の値がないから nil ってのはごく自然な解釈だとも思うんだよなぁ。
6:05 AM
これは、内部表現としてストレージがあるイメージではないでしょう
Avatar
うーん、まあたしかにそうかも?
Avatar
omochimetaru 4/21/2017 6:05 AM
Arrayっていうデータ構造抽象から
6:05 AM
想像する話しとしてはヒネリを感じる
Avatar
じゃあ、 birthday: Date? を持ってる User 型に対して、 birthYear を取り出す処理はどっち? (edited)
Avatar
omochimetaru 4/21/2017 6:07 AM
「亜空間none」っていう概念良さそう。
Avatar
実際には
6:08 AM
Optional<Optional<Int>>が正しい型ですよねそれ
Avatar
norio_nomura 4/21/2017 6:08 AM
Optionalthrows のオーバーロードが推測でうまく扱えるようになったとして、じゃあそんなメソッドを書くときは実行速度の観点から Optional 版を書いてそれを throws 版でラップする形になる?
Avatar
?のお陰でネストが解消されてるだけ
Avatar
omochimetaru 4/21/2017 6:09 AM
それは Int? 。空としてのnoneはbirhtdayのストレージのところに実在してるから
6:09 AM
そのnoneが素通しで見えてくるだけで
6:09 AM
亜空間ではない
Avatar
あ、birthYearはIntか、ややこしいな
Avatar
内部構造として birthday: Date? を保持しているのか、 birthYear/Month/Date : Int? を保持しているのかはカプセル化された中の話。
6:10 AM
つまり全部 Optional ってことね。 > @omochimetaru (edited)
Avatar
omochimetaru 4/21/2017 6:10 AM
もちろんカプセル化されてるけど、そういう風に素直に捉えられると思う。
6:10 AM
はい。
6:10 AM
じゃあそんなメソッドを書くときは実行速度の観点から Optional 版を書いてそれを throws 版でラップする形になる?
6:10 AM
内部の実装はそのほうが速くて良さそうですね
6:10 AM
nilだったら情報乗っけたエラーを組み立てる、というコード
Avatar
実際にどういう風にデータを保持しているか、動的に生成されているかには関係なく、メンタルモデルとしてそのような値そのものが存在しているように感じられるか、 first のように一段抽象度の高い概念かどうかだと。
Avatar
omochimetaru 4/21/2017 6:11 AM
そういうことです
6:11 AM
メンタルモデルと実装モデルが実際は真逆ってことはありえるけど
6:11 AM
APIとして見せる時に
6:11 AM
どっちのメンタルモデルをユーザーに伝えたいか、できめる。
Avatar
@norio_nomura 恐らく需要の面からもguard let throwsが言語機能として提供される、という感じになると思います
6:14 AM
そういう意味だと???と同じなのか
Avatar
norio_nomura 4/21/2017 6:28 AM
試しに ??? を実装して使ってみるとか
Avatar
struct OptionalError: Error { let file: String let function: String let line: Int } extension Optional { func `throw`(file: String = #file, function: String = #function, line: Int = #line) throws -> Wrapped { guard let wrapped = self else { throw OptionalError(file: file, function: function, line: line) } return wrapped } } オペレーターで十分な情報を取る方法が思いつかなかった (edited)
Avatar
omochimetaru 4/21/2017 6:38 AM
Optionalに生やすならtryじゃなくてthrowメソッドがいいんじゃないか
6:38 AM
throwあれだったらraiseにするとか
Avatar
あーそうね
6:40 AM
で、これがあると
6:41 AM
あかん、ワンライナーで書いたら全部おなじになる、ザコだなー
6:45 AM
ワンライナーはだめだけど、 do { let user = try User( name: name.throw(), age: age.throw(), gender: gender.throw() ) } catch { throw User.Error.decodeFail(error) } こんな感じにしてサクッと特定できる世界観にはなりますね
Avatar
norio_nomura 4/21/2017 6:54 AM
チェインの途中でどこが nil だったか知りたいみたいなのには応えられるのかな (edited)
Avatar
チェインを1行ずつ分解すればまぁ
Avatar
norio_nomura 4/21/2017 6:57 AM
#line で分岐とかゾッとするので、Mirror とか使うといいのかな (edited)
Avatar
うーん、現行の仕様だと、Wrappedとこの3つぐらいしか情報が取れない気がしていて
6:58 AM
Mirrorって自身の変数名とか知れましたっけ?
6:58 AM
無い気がする
6:59 AM
なのでそのレベルの言語サポートが欲しいよねって感じですね
Avatar
norio_nomura 4/21/2017 7:04 AM
ということは ??? とは別物って感じですね。
Avatar
現状は完全な再現は出来ないと思います
7:04 AM
???のプロポーサルちゃんと読んでないから誤解があるかもしれない
Avatar
norio_nomura 4/21/2017 7:05 AM
ああ、それは僕も読んでないやw
7:12 AM
??? は出てこないけど。
Avatar
Error型を作って差し込む感じか
Avatar
first とかも含めて SDE なんてなくして適切なエラー情報込みで throws にすべきだとして、 ??? はいるんですっけ?現実的に first とかが Optional を返すからってこと?
Avatar
現実の問題としてSDEや曖昧なものが全てOptionalに寄せられていて
7:51 AM
Error型が欲しい人はguard使うけどchaining出来ないし、構文レベルでthrowsへの変換があれば満足できるのではないか、ということだと思いました。 (edited)
Avatar
お、↓ならできました。 extension Array { func first() throws -> Element { guard let value = self.first else { throw EmptyError() } return value } } struct EmptyError: Error {} let array = [2, 3, 5] let a = array.first let b = try! array.first() print(a) // Optional(2) print(b) // 2 (edited)
7:58 AM
なんで array.first は ambiguous にならないんだろう?
Avatar
extensionで分離しているところがポイントっぽい?
8:00 AM
あれ、ダメですね、ライブラリかな
Avatar
↑のコード実行できませんでした??
Avatar
いや、自作の型で同じことをやろうとして
Avatar
プロパティとメソッドのオーバーロード?
Avatar
extensionに分離したけどダメだった→ライブラリでコンパイル済みの型なら通るのでは説
8:01 AM
class C { var s: String? { return "a" } } extension C { func s() throws -> String { return "b" } }
8:01 AM
これですね
Avatar
ほんとだ。謎・・・。
Avatar
ファイルが別でも通る可能性あるな
Avatar
同じパッケージだとダメなんですかね?
Avatar
なんかファイルとかパッケージとか
8:03 AM
そのあたりを分けるとコンパイラパワーが増える(?)というのは確認していて
8:03 AM
通らないはずの型が通るようになったりとかままある
Avatar
なるほど・・・
Avatar
逆に通らなくなるのもあったな、この間のとか
Avatar
ひどいw
Avatar
extension Array { var first: Element? { return nil } } 普通にこれが通るので
Avatar
あー
8:16 AM
Arrayさんを拡張してるからですか
Avatar
他モジュールのメソッドとかはオーバーライド可能ってことになっている。
Avatar
モジュールか
Avatar
@rintaro
他モジュールのメソッドとかはオーバーライド可能ってことになっている。
これの影響範囲はオーバーライドした側のモジュール内にとどまるんですか?
8:32 AM
あと、 func first() throws -> Element はオーバーライドじゃなくてオーバーロードですよね?これが同一モジュールだとできないのにモジュール外だとできるのはなんでなんでしょう??
Avatar
試してないですが、 public にしたら他モジュールからも見えると思います。 // ModuleA public extension Array { public var first: Element? { return nil } } // ModuleB import ModuleA let a = [1,2,3].first とかしたらambigousになると予想。 (edited)
8:35 AM
オーバーライド でも オーバーロード でも モジュール外の「名前」との衝突は一切考慮されないっていう実装ですね。
Avatar
静的ディスパッチはいいとして、動的ディスパッチだと仮想関数テーブルを拡張しないとできないような??
Avatar
witness-table、確かライブラリ超えて拡張できなかった気がする
8:36 AM
UIViewContorllerにXCTestだけprotocol書き換えて、Environment変更しようとしたら失敗したw
Avatar
試してないですが
試しました。ambigous にならずに ModuleA 実装が優先されましたw
Avatar
import ModuleA してなければ元の first が実行されるんですよね? (edited)
Avatar
// ModuleA public extension Array { public var first: Element? { return nil } } // ModuleB public extension Array { public var first: Element? { return self[0] } } // main import ModuleA import ModuleB let a = [1,2,3].first さすがにこれはambigous (edited)
8:48 AM
import ModuleA してなければ元の first が実行されるんですよね?
じゃなかったら大変
Avatar
そこが import でコントロールできるんだったら、 extension メソッドにプレフィックスつけたりネームスペース切ったりするのが流行ってたけど不要?
8:49 AM
両方 import したくて衝突したときに、どっちか指定する方法がないのか・・・。
8:50 AM
foo.bar にせずに foo.rx_bar とか foo.rx.bar みたいなやつ。
Avatar
importした上で元のものを使う手段が無さそう?
Avatar
!!! // ModuleA public extension Array { public var first: Element? { return nil } } // ModuleB import ModuleA public extension Array { public var first: Element? { return self[0] } } // main import ModuleB let a = [1,2,3].first これでambigous。これはまずいんじゃ・・・
8:53 AM
// ModuleA public extension Array { public var first: Element? { return nil } } // ModuleB import ModuleA // main import ModuleB let a = [1,2,3].first これはnil になる。まずすぎる (edited)
Avatar
おお、それはまずそうですね。。。 < ambigous (edited)
8:55 AM
ここは @rintaro さんの出番では?👍
Avatar
バグリポート上げるくらいしかできませんw
8:58 AM
Avatar
っぽいですね。
9:00 AM
コメントw
Old, old bug. 🙂
Avatar
struct Matrix { var elem: [[Float]] } について 可 let a: [[Float]] = [[1, 2], [1.0/2 1.0/3]] _ = Matrix(elem: a) 不可 _ = Matrix(elem: [[1, 2], [1.0/2 1.0/3]])
5:24 AM
なんとかならんのでしょうか
Avatar
_ = Matrix(elem: [[1.0, 2.0], [1.0/2.0 1.0/3.0]]) これもだめですかね
Avatar
SwiftSandboxで警告出てましたねそこ
5:25 AM
それでもだめっぽいです
5:26 AM
ERROR at line 9, col 31: cannot convert value of type 'Double' to expected element type 'Float' _ = Matrix(elem: [[0, 1], [1.0/2.0, 1.0/3.0]]) ~~~^~~~ Float( )
Avatar
nんー
Avatar
XCodeの方で何故かDouble/Intの警告出てなかったです
Avatar
struct Matrix { var elem: [[Float]] } _ = Matrix(elem: [[1.0, 2.0], [1.0/2.0, 1.0/3.0]])
5:27 AM
これで通りましたね、Sandbox
5:27 AM
Xcodeはインスコ中なので動かせない
Avatar
omochimetaru 4/22/2017 5:29 AM
なんかチャンネルふえてるな
Avatar
あれ?同じ文でこちらでは通らないですね…… (edited)
Avatar
Xcodeは通らない
Avatar
僕の方はSwiftSandboxでも通らなかったです
Avatar
おっと…
5:49 AM
Sandbox、3.0だった。
5:49 AM
3.1は通らないですね
Avatar
昔は行けてたとなるとバグの可能性ありですかね?
Avatar
3.0から3.1で型周りで変更結構あるので、間違いなくそれらの影響何だと思いますが、
5:54 AM
バグかと言われるとどっちだろう、という気がする
5:55 AM
でも_ = Matrix(elem: [[1.0, 2.0], [1.0/2.0, 1.0/3.0]]) これが通らないのはバグな気がする
Avatar
一度[[Float]]に代入するところができますからねぇ
Avatar
6:30 AM
/// - Parameters: /// - optional: An optional value. /// - defaultValue: A value to use as a default. `defaultValue` is the same /// type as the `Wrapped` type of `optional`. public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
6:31 AM
昨日の話題
6:31 AM
??オペレーター、既に???とのオーバーロードですねこれ
Avatar
omochimetaru 4/22/2017 6:31 AM
intOpt ?? throw HogeError() こう書けるって事?
Avatar
intOpt ?? HogeError() (edited)
6:32 AM
これでおkす
Avatar
omochimetaru 4/22/2017 6:33 AM
それは ?? の右側のオートクロージャーの返り値の型が () -> Tじゃなくて () -> HogeErrorになってコンパイルエラーでは
Avatar
いや、通る
6:36 AM
public func parse(data: Data) throws -> Any { return UIImage(data: data) ?? Error.imageNotFound }
6:36 AM
あーー
6:36 AM
Anyのせいか
Avatar
_ = Matrix(elem: [[1, 2], [1.0/2 1.0/3]]) は master で -Xfrontend -propagate-constraints ていう experimental なフラグ付けたら通りました。
Avatar
https://github.com/apple/swift/pulls?utf8=%E2%9C%93&q=is%3Apr%20is%3Aclosed%20constraint%20propagation%20 このあたりかな。そろそろ enabled by default になりそうな感じなので Swift4 では直ってるとおもわれます。
swift - The Swift Programming Language
Avatar
なるほど。情報ありがとうございます。
Avatar
norio_nomura 4/22/2017 1:14 PM
ほう enum Error: Swift.Error { case unavailable } let dictionary: [AnyHashable:Any] = [:] do { _ = try dictionary["unavailable"] ?? { throw Error.unavailable }() } catch { print(error) // "unavailable\n" } (edited)
Avatar
extension Error { func `throw`<T>() throws -> T { throw self } } struct MyError : Error {} let str = "hoge" do { try print(Int(str) ?? MyError().throw()) } catch { print(error) } いやーw
Avatar
今日一日???導入してコード書いてみたけど結構快適だった
3:42 PM
Error型にthrowでthrows->Tになるの良いですねこれ
Avatar
norio_nomura 4/22/2017 4:25 PM
そうか -> T にしないとダメですね。 try dictionary["unavailable"] ?? { throw Error.unavailable }() みたいに、期待される型が Any だとエラーにならない。
Avatar
norio_nomura 4/23/2017 2:32 PM
extension Swift.Error { func `throw`<T>() throws -> T { throw self } } extension Optional { func `else`<T: Swift.Error>(_ error: @autoclosure () -> T) throws -> Optional { guard case .some = self else { throw error() } return self } func unwrap<T: Swift.Error>(or error: @autoclosure () -> T) throws -> Wrapped { guard case let .some(wrapped) = self else { throw error() } return wrapped } enum Error: Swift.Error { case isNone(String) } func `else`(_ message: @autoclosure () -> String) throws -> Optional { guard case .some = self else { throw Error.isNone(message()) } return self } func unwrap(or message: @autoclosure () -> String) throws -> Wrapped { guard case let .some(wrapped) = self else { throw Error.isNone(message()) } return wrapped } } enum Error: Swift.Error { case unavailable, notInt } let dictionary: [AnyHashable: Any] = ["available": 1] do { let a = try (dictionary["available"] ?? Error.unavailable.throw()) as? Int ?? Error.notInt.throw() let b = try dictionary["available"].unwrap(or: Error.unavailable) as? Int ?? Error.notInt.throw() let c = try dictionary["available"].map({ try ($0 as? Int).unwrap(or: Error.notInt) }).unwrap(or: Error.unavailable) let d = try dictionary["available"].map({ try $0 as? Int ?? Error.notInt.throw() }) ?? Error.unavailable.throw() let e = try dictionary["available"].else(Error.unavailable).map({ $0 as? Int }).unwrap(or: Error.notInt) let f = try dictionary["available"].else("\"available\" does not exists").map({ $0 as? Int}).unwrap(or: "Fail converting to Int") } catch { print(error) } 🤔
Avatar
https://github.com/apple/swift/pull/8939 associatedtypewhere を付けられるようになって、 Sequence.Iterator.ElementSequence.Element になるのはうれしいんだけど、 https://github.com/airspeedswift/swift/blob/8869509174859ca30eeca37001463b3b46e9f7fc/stdlib/public/core/Sequence.swift#L330-L331 associatedtype Element associatedtype Iterator : IteratorProtocol where Iterator.Element == Element こう宣言しなければいけないのは直感的ではないなー。 associatedtype Iterator : IteratorProtocol typealias Element = Iterator.Element で実現できなかった理由はなんなんだろう。
Adds an associatedtype Element to Sequence, then constrains Iterator.Element to match it.
swift - The Swift Programming Language
Avatar
protocolの型をtypeliasで束縛するの、3.1から使えなくなっていて
4:22 AM
ネストしたGenerics型とかの兼ね合いかな~と想像してるんですが
Avatar
直感的ではないなー。
そうでもない気がしてきた。 Element を起点に考えれば当然の帰結か。
Avatar
omochimetaru 4/24/2017 4:24 AM
whereって条件って感じだけどなんでwhereなんだろ?
Avatar
うーん、 Sequence はあくまで Iterator を生成するものなんだから、やっぱ Iterator 起点なのが直感的な気が。
4:24 AM
↓ができるならそっちの方がいい気がする。 associatedtype Iterator : IteratorProtocol typealias Element = Iterator.Element (edited)
Avatar
associatedtype Iterator : IteratorProtocol associatedtype Element where Element == Iterator.Element もできるのかな? (edited)
Avatar
お、できそう
4:26 AM
protocolにtypealias書けないのはまあなんとなく理解できていて
Avatar
それって自由度が何もないのに associatedtype って変じゃないですか?
Avatar
なのでassociatedtypeで実現しようとすると、=だとデフォルト実装になって書き換えれてしまう。
Avatar
omochimetaru 4/24/2017 4:27 AM
typealiasだと意味が曖昧になるケースが出るってことかな
4:27 AM
既存の用法とのカチ合いで
Avatar
@omochimetaru typealias Element = Iterator.Element って既存用法と何か違うっけ?
Avatar
omochimetaru 4/24/2017 4:28 AM
それって、
4:28 AM
もし、Sequenceに親プロトコルがあって
4:28 AM
その親プロトコルがElementっていうassociated typeを持っている場合に
4:29 AM
それを確定させるっていう意味になるのか
Avatar
そうそう
4:29 AM
そういう問題が発生し得るので
Avatar
omochimetaru 4/24/2017 4:29 AM
Sequence自体のネームスペースにElementっていうシンボルであるassociatedtypeを定義するのか
4:29 AM
あいまいにならない?
Avatar
protocolではtypealiasは書けない、としていたほうが
Avatar
omochimetaru 4/24/2017 4:29 AM
ということを思い浮かんだ 多分たるのんもいっしょ
Avatar
一貫性が持てそう
Avatar
omochimetaru 4/24/2017 4:29 AM
それか、classでのその用法と紛らわしい(厳密には衝突はしないけど紛らわしいから避けたい系 (edited)
4:30 AM
本当に今の仕様でぶつかるかは自信無い
Avatar
typealiasprotocol に復活したときに typealias Element = Iterator.Element いけるじゃん!みたいなので騒いでいたのは事実で https://github.com/apple/swift/pull/1610
Split up parsing of typealias and associatedtype, including dropping a now unneeded ParseDeclOptions flag. Then made typealias in a protocol actually valid, which works great except that you can't ...
Avatar
あー、 associatedtype を縛る方は typealias のままだったのか。書くことないから忘れてた。 https://twitter.com/chriseidhof/status/700305519328755712
In Swift 2.2, when using associatedtype, you still have to use typealias to declare an associated type instance:
🙄 1
4:36 AM
これ↑みたいに、縛る方は associatedtype Foo = Bar の方が良くないのかな?何かダメな理由あるっけ?
Avatar
protocolだとassociatedtype Foo=Bar は束縛じゃなくてデフォルト実装なんですよ
4:37 AM
上書き可能
Avatar
@chriseidhof That's probably a common enough mistake to be worth a fixit. Got time to file a bug?
Avatar
マジか
Avatar
associatedtype のデフォルト実装ってどんなときに使うんですか?
4:39 AM
@tarunon いや、 2.2 の頃の話なので、その後どういう話になったのかが気になります。
Avatar
ある型のassociatedtypeが一般的に期待される型があり得る場合ですね、 stdlibでもそこら中にありますよ
Avatar
Joe Groff のツイートは エラーメッセージに fix-it つけてわかりやすいようにすべき。って話ですね。
4:42 AM
束縛を associatedtype でやるっていう話ではない。
Avatar
おお、そうなんですね。勘違いしてました。
4:45 AM
@tarunon そうなんですね・・・。 associatedtype って大体↓みたいな感じで暗黙的に解決されちゃって明示的に指定することがないんで、デフォルト実装がありがたいイメージがありませんでした。 protocol Foo { associatedtype Bar func bar() -> Bar } struct Baz: Foo { func bar() -> Int { return 42 } } (edited)
Avatar
えーと
4:48 AM
一番嬉しいのはですね
4:49 AM
protocol Foo { associatedtype Bar = Void func bar() -> Bar } extension Foo where Bar == Void { func bar() -> Bar {} } struct Baz: Foo { // 書かなくてもBar==Voidが推論される }
4:49 AM
このパターンですね
4:49 AM
書けば推論されるのはその通りなんですが、デフォルト実装を持っている場合は、書かなくて推論されることが嬉しい場合が結構ある
Avatar
omochimetaru 4/24/2017 4:50 AM
C++だとコンテナのメモリ管理をAllocatorっていう型パラに切っておいてデフォルトではmalloc/freeのやつで埋めとくみたいなのありますね
Avatar
@tarunon なるほど。
Avatar
omochimetaru 4/24/2017 4:52 AM
アップルの人もこのPRについてツイートしてた (edited)
Soon you'll be able to say 'T.Element == ...' instead of 'T.Iterator.Element == ...' in your where clauses: https://t.co/hjXqfTpEtY
Avatar
実際にはIterator.Element==Elementでしかないのに、Elementを分けて書いたのが呪いの始まりなのでは?という気もしている
4:53 AM
横着してはいけなかった
Avatar
omochimetaru 4/24/2017 4:56 AM
横着ではなくない?イテレーターはそれ単体で綺麗に独立してるよ (edited)
Avatar
いや
4:56 AM
SequenceがElementを持ってるのはそれはそうだけど
4:57 AM
言語機能としてElement == Iterator.ElementをSequence単体で実現するすべがない状態で
4:57 AM
ElementとIteratorを定義してしまったのはまずかったのでは、という視点 (edited)
Avatar
うーん、 SequenceElement を持ってない気がします。 SequenceIteratorFactory にすぎない気が。
Avatar
omochimetaru 4/24/2017 5:00 AM
あーー
Avatar
Java の Iterable<E>E を指定して Iterator<E> を返すけど、 Swift の SequenceIterator の種類まで決定するという意味で違いがありそうな。
Avatar
omochimetaru 4/24/2017 5:01 AM
シーケンスにおけるエレメントって、ラムダ計算の自由変数なのかな
5:02 AM
プログラミングだと束縛変数しか基本出てこないからシーケンスに暗黙にTが引数として存在するような気分になるけど
5:04 AM
>ラムダ式は自由変数( λ によって束縛されていない変数)を含むこともできる。例えば、入力に関係なく常に y を返す関数を表す式 λx. y において、変数 y は自由変数である。
5:04 AM
うまくいえない・・・
Avatar
この変更でこれが通らなくなりそうです。 struct AlwaysOneIterator : IteratorProtocol { func next() -> Int? { return 1 } } struct AlwaysOneSequence : Sequence { func makeIterator() -> AlwaysOneIterator { return AlwaysOneIterator() } } (edited)
5:16 AM
associatedtype Element が解決できないみたい。
Avatar
typealias Element = Intを書かないといけないのかな
5:22 AM
associatedtype Element associatedtype Iterator : IteratorProtocol where Iterator.Element == Element // ↑これだとElementをIteratorから推論できない associatedtype Iterator : IteratorProtocol associatedtype Element = Iterator.Element where Element == Iterator.Element // ↑この書き方ができるなら、ElementはIteratorから推論可能。
5:23 AM
こういうことかな
5:23 AM
後者のほうが良さそう
Avatar
どっちでも違いなさそうですね。手元のが 3,4日 前のmasterなので、今 pull し直して確認中です。 (edited)
Avatar
むむぅ。件のPR適用してビルドした状態で、これは通らないのに、 protocol MySequence { //associatedtype Iterator : IteratorProtocol //associatedtype Element where Element == Iterator.Element associatedtype Element associatedtype Iterator: IteratorProtocol where Iterator.Element == Element func makeIterator() -> Iterator } struct AlwaysOneIterator : IteratorProtocol { func next() -> Int? { return 1 } } struct AlwaysOneSequence : MySequence { func makeIterator() -> AlwaysOneIterator { return AlwaysOneIterator() } } struct AlwaysOneSequence : MySequencestruct AlwaysOneSequence : Sequence に変えると通るようになる。
Avatar
えw
5:41 AM
悪魔の加護かな
Avatar
今、社内 Slack で Scala の拡張 for 式について話してたんですが、 @tarunon さんあたりは Swift にも Higher kinded type と Haskell の do 記法的なものがほしい派ですか?
Avatar
Haskell doについては
Avatar
何度も Core Team に否定されているので実現は難しそうですが・・・。
Avatar
既存のdo構文が、asyncでも動くようになれば
7:33 AM
殆どの要求は満たせそう
Avatar
モナドの用途はほとんどが ResultPromsie で、 throwsasync があれば <-tryawait で代用できるから、それで大体 OK ってことですか?
Avatar
はい
7:34 AM
用途は殆どが、というとちょっと乱暴だな
7:35 AM
ただ、多くの問題はResultとPromise、これらの複合が発生した場合に
Avatar
Rx 使ってると Opservable もあるかと思いましたが、あれは色んなオペレータ組み合わせて使うし flatMap だけできてもって感じですか?
Avatar
ネストがひどいことになる、それさえdo構文で解決できれば
7:35 AM
いえ、どちらかと言えば
7:36 AM
あー
7:36 AM
まあObservableはそうですね、まだちゃんと思考してないんですが
7:37 AM
組み合わせでオペレーター使いざるを得ないからdoの中で解決するのは出来ないのでは?という気がしています
Avatar
なるほどー。
Avatar
asyncがあれば、うまいことやれば、Observableのかなりの需要を食えるのでは?というのもなんとなく考えてます
7:39 AM
ちょっとちゃんと考えてないのではっきり言えないですが
Avatar
値型のおかげでイミュータブルプログラミングの出番も少ないし、 IO モナドとかもいらないし、 Result, Promise あたりがやっぱメインですよね。
7:40 AM
Observableのかなりの需要を食えるのでは?
これ思います。実は Promise で済むケースが多そう。
Avatar
Higher kinded type
こいつは欲しいんですよねぇ。これがないせいで、型消し使うシチュエーションが多すぎる
7:40 AM
Any<Sequence where>なんちゃらも、この問題を解決出来る…わけではないですよね、恐らくパフォーマンスに影響が出る
Avatar
Higher kinded typeはほしいですねぇ。 Self はあるのに Higher kinded type はないのと、 associatedtype があるとプロトコル型変数作れないのに associatedtype がなければ作れるのは何か中途半端感を感じます。
Avatar
@rintaro 今のmaster, SequenceにElementは定義されてないように見えます。 https://github.com/apple/swift/blob/master/stdlib/public/core/Sequence.swift
swift - The Swift Programming Language
Avatar
swift - The Swift Programming Language
Avatar
omochimetaru 4/24/2017 8:32 AM
> Observableのかなりの需要を食えるのでは? これ思います。実は Promise で済むケースが多そう。
これ僕も思って本気でライブラリ作ってユースケース洗い出してってやっていたら
(edited)
8:33 AM
やっぱりObservableが要るって結論になった。 (edited)
Avatar
ダメか…
8:34 AM
Streamの合成がasync throws funcの合成と等価じゃないから
Avatar
omochimetaru 4/24/2017 8:34 AM
Promiseだけじゃなくて、EventEmitterとVariableは欲しいんですよね
8:34 AM
で、そいつらがObservableとして同じ基盤に乗ってないと、相互接続ができないし、
Avatar
ふーむ
Avatar
omochimetaru 4/24/2017 8:35 AM
たとえば、
8:35 AM
マウスクリックのイベントを受けて、URLリクエストを発火する
8:35 AM
みたいなパターンを考えた時点で
8:36 AM
EventEmitterとPromiseが相互にflatMapできないと
8:36 AM
接続点でボイラープレートみたいなのがワチャワチャでてきちゃうし
Avatar
結局記述量変わらなくなりますよね
Avatar
omochimetaru 4/24/2017 8:37 AM
EventEmitterだとmapしてEE <T> から EE<U>つくったとき on の連鎖どうなんのとか
8:37 AM
・これもできるならあれもできないとおかしい っていうのがどんどんでてきて
8:37 AM
それってRx.Observableの再実装が必要では?みたいになってしまった
8:38 AM
Everything is streamみたいに突き抜けたところまでいかなくても
8:39 AM
EventEmitter, Promiseの2つを使うより素朴にObservable使ったほうが同じことをよりスッキリかけちゃうなあ
8:39 AM
という感じですね
8:40 AM
最近SingleもRxSwiftに入ったから「1個」という観点での型表明も強化されたし
8:40 AM
MaybeとCompletableがある分、Promiseより強いんでは?とも思う
Avatar
うーん、イベント発火する部分がシンプルなfunctionの世界になれば合成はどうにかなるかなぁと思ってたけど
Avatar
omochimetaru 4/24/2017 8:43 AM
それって結局Promiseからはみ出すのと
Avatar
やっぱり無理か、こういうのは書かないと真に理解出来ない。
Avatar
omochimetaru 4/24/2017 8:43 AM
Promiseの、値一個だけっていう概念が邪魔になる
Avatar
連続させるのがいちいち手間で、結局allに包ませることになるのが辛いです
Avatar
omochimetaru 4/24/2017 8:44 AM
Promiseだとキャンセルのしくみも自分で作り込まないといけないんで
8:45 AM
DisposeBagで全部片付けてしまえ〜 みたいな段階にいくまでの積み木が結構たいへん
Avatar
DisposeBagというか
8:52 AM
Completedの概念が非常に優れているんですよね
8:52 AM
最近理解したの、Observableが持つクロージャにリファレンスカウントを増やさせることで
8:53 AM
任意の参照可能なオブジェクトにフィールドを持たせる必要すら無かった。
8:53 AM
CompletedすればObservableが破棄されるのでメモリリークも無い。
Avatar
omochimetaru 4/24/2017 8:53 AM
ん、でもそれはObservableがsubscriberを登録できるっていう仕組み経由でひっかけてるって話ですよね?
Avatar
そうですね
8:53 AM
最終的にはDisposeBagが持っています
Avatar
大域でいらないオブジェクトはオブザーバブル繋ぐメソッドのスコープに置くとかはよくやりますね
Avatar
omochimetaru 4/24/2017 8:54 AM
元をたどればsubscriber の配列をもっている事が、そのカスタマイズ性を提供してる
Avatar
@tarunon さっき話してた、letで自己再帰するやつ、面白いのあるから書いた https://gist.github.com/omochi/945fbf77566ab507dd95783f2f64deae (edited)
😎 1
Avatar
オッ
12:20 PM
Prologみたいだ
Avatar
ML系では実際まさにこれな rec って言語機能があるとかないとか、そんな話を資料で読んだ
12:23 PM
面白いところだけ転載しとこう // let + クロージャー (と小道具)で再帰 let fib3 = rec { (fib: (Int) -> Int, x: Int) -> Int in switch (x) { case 0: return 0 case 1: return 1 default: return fib(x - 2) + fib(x - 1) } }
12:27 PM
38:40 くらいから
Avatar
不動点コンビネータってやつですね
Avatar
@ukitaka あ〜これがそれですね(いつも細かい話は毎回忘れてしまいます
Avatar
この当時ってネストしたローカル関数も再帰できなかった記憶があります。
Avatar
omochimetaru 4/25/2017 1:51 AM
https://developer.apple.com/videos/play/wwdc2014/404/ これを思い出した。 38:40 くらいから
見てきた。メモ化高階関数も対象の関数が自己再帰を含むから同じ形になるんですね。
Avatar
norio_nomura 4/25/2017 4:10 AM
swift-3.1.1-RELEASE 何が変わったのか
Avatar
https://github.com/apple/swift/compare/swift-3.1-RELEASE...swift-3.1.1-RELEASE deinit まわりのメモリ問題とか入っているっぽい。
swift - The Swift Programming Language
Avatar
norio_nomura 4/25/2017 4:18 AM
Xcode 8.3.2がSwift 3.1.1らしいから、Xcodeでも直ってるってことか。
Avatar
Xcode 8.3.2 はまだ Swift3.1 だと思いますが、どうなんだろう。
Avatar
でも最適化の時のバグは治ってましたね
Avatar
norio_nomura 4/25/2017 4:22 AM
https://swift.org/download/#releases には "*Swift 3.1.1 is available as part of Xcode 8.3.2." とあります (edited)
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
NSErrorキャストでクラッシュするのと、2重ループのメモリリーク
Avatar
$ swift -version Apple Swift version 3.1 (swiftlang-802.0.53 clang-802.0.42) Target: x86_64-apple-macosx10.9 表記だけの問題?
Avatar
動作的には明らかに 3.1.1 なんだけど #if swift(>=3.1.1) print("3.1.1") #endif これが true にならないのとか、ほんとにイケてない。
Avatar
omochimetaru 4/25/2017 5:15 AM
中身は3.1.1だけど表示だけ3.1だからみたいな
Avatar
中身と表示一致してないのダメでは
Avatar
main.swift でトップレベルで guard した場合って else ブロックに何書けばいいんでしょうか? fatalError とかでなく正常終了したい場合。 return はできないようです。 "swift top level guard exit" とかで軽くググってみたんですがよくわからず・・・。
Avatar
abort() とか?
10:00 AM
Neverなメソッドなら書けるはず
Avatar
@koher さっきわかんないって言ったけどそういえばこんな例はあります https://github.com/apple/swift-package-manager/blob/master/Sources/POSIX/exit.swift
swift-package-manager - The Package Manager for the Swift Programming Language
Avatar
exit(1) abort() fatalError() らへんが使えると思うけど違いは分からない
10:01 AM
正常終了なら exit(0) ?
Avatar
posix的にはそう stdlib.hの EXIT_SUCCESSを使うのがお行儀が良い
Avatar
MAIN: do { // ... guard ... else { break MAIN } // ... }
Avatar
育ちが悪いからexit(0)しちゃう
Avatar
でもCの作法を呼べるってだけでSwiftのやりかたかといわれると微妙
Avatar
うーん、たしかに exit 呼べばいい気がしてきました。 exit ってちゃんと Never になってるんですね。
Avatar
@rintaro ぼくもよく func main() { } main() ってやってます
10:03 AM
@koher C向けのアトリビュートが良い感じに検出されてるっぽい
Avatar
素直に func に突っ込んじゃうのが楽ですよね。
Avatar
__attribute(noreturn)__ だったっけ。 (edited)
10:04 AM
C向けっていうかclang/gcc
Avatar
へえー
Avatar
@hiragram さん、ありがとうございます。
Avatar
いえいえ
Avatar
func main() { } main() ↑これは main() のコールが C とかより冗長で負けた感が・・・。 (edited)
Avatar
トップレベルなんて信じてない
10:05 AM
負けた感はある
10:06 AM
(僕はrubyでもよくdef mainからはじめてる
Avatar
コマンドラインのスクリプト書いてて正常終了したいんだから普通に exit(0) が素直だった。 (edited)
10:07 AM
Never になってるの素晴らしい。
Avatar
exit(EXIT_SUCCESS) も呼べると思います。
Avatar
お、いけました!ありがとうございます。 < EXIT_SUCCESS
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
ふと気になったんですが、Optionalなクロージャを引数に作ると、@escaping 書けなくなりますよね。どういう扱いなんだろう。 func hoge(_ arg: (() -> ())?) {...} // ←みたいなことをした時に、argがエスケープされるとしてもそれを明記できない。
Avatar
それは
Avatar
Optionalがキャプチャするから常にescapingかな
Avatar
自動 @escaping 扱いです。
Avatar
ただのプロパティだから
10:44 AM
必然的に常にエスケープする
Avatar
ここに書き込んだ瞬間に気がついた
Avatar
Optinalはただの型だから。
Avatar
Foo<() -> ()> と同じですしね。
10:46 AM
? の記号は便利だけど、こういう混乱を招きやすい・・・。
Avatar
そうすると
10:48 AM
引数のクロージャを省略可能にしようとすると
10:48 AM
最適化で不利になる?
Avatar
可能性はありそう。
10:50 AM
Swift コンパイラがすごく賢ければ
10:50 AM
そこも考慮してインライン化してくれたりするかもだけど。
Avatar
今度試してみよ
Avatar
もしかしたら
10:51 AM
func hoge(_ arg: (() -> ())?=nil) {...} func hoge(_ arg: (() -> ())={ _ in }) {...} 後者のほうが強いのかもしれない (edited)
Avatar
インライン化されて完全に消える事を考えるとありえるね
Avatar
呼び出しコストかかるかと思いましたが消えるんですかねこれ
Avatar
llvmir出してみて
10:53 AM
たらわかる
Avatar
SE-0171 ができるようになったらこんな感じかな? let strings = ["a:2", "b:3", "c:5"] let dictionary = strings.reduce(into: [:]) { (r: inout [String: Int], e) in e.components(separatedBy: ":") => { r[$0[0]] = Int($0[1])! } } // ["a": 2, "b": 3, "c": 5] (edited)
10:59 AM
=> は前話してた Kotlin の let 代わり。
Avatar
できそう
Avatar
norio_nomura 4/25/2017 2:59 PM
e.components(separatedBy: ":") => { r[$0[0]] = Int($0[1])! } これの型はどこで決まるの?
Avatar
rから推論できそう
Avatar
omochimetaru 4/25/2017 3:26 PM
=>は中置オペレータで式の評価結果はクロージャの評価結果そのもの
3:26 PM
あれ?Swiftって代入文の評価結果ってVoidじゃなかったっけ
3:26 PM
右辺値だったっけ。
Avatar
あー
Avatar
vogdですね
3:27 PM
void
Avatar
omochimetaru 4/25/2017 3:27 PM
voidか。あ、でもいいのか。 inout版のreduceは
3:27 PM
reducerは返り値voidで、inoutで固定なのか。
3:28 PM
とりあえず、 => の定義 https://github.com/koher/swiflet
swiflet - Provides => like let in Kotlin for Swift
Avatar
kotlin let知ってないと目がぐるぐるする
3:29 PM
🌀
🙃 1
Avatar
inoutじゃないけどvoidを返す場合を考えたけどそんなのなかった
Avatar
なるほど infix operator => public func =><T, U>(lhs: T, rhs: (T) throws -> U) rethrows -> U { return try rhs(lhs) } extension Sequence { func reduce<A>(into initial: A, _ combine: (inout A, Iterator.Element) -> ()) -> A { var result = initial for element in self { combine(&result, element) } return result } } let strings = ["a:2", "b:3", "c:5"] let dictionary = strings.reduce(into: [:]) { (r: inout [Int: String], e) in e.components(separatedBy: ":") => { r[$0[0]] = Int($0[1])! } } error: cannot subscript a value of incorrect or ambiguous type e.components(separatedBy: ":") => { r[$0[0]] = Int($0[1])! } ^~ 型推測しきれないぽい。 (edited)
Avatar
呼び出し側にinto: ラベルが必要です (edited)
Avatar
into: 足してもエラーは変わらず。
Avatar
let dictionary = strings.reduce(into: [:]) { (r: inout [String: Int], e) in e.components(separatedBy: ":") => { r[$0[0]] = Int($0[1])! } } で通りました。[Int: String] じゃなくて [String: Int] でしたね。
Avatar
おお、追加のアノテーションなしでいけるんですね。
Avatar
omochimetaru 4/26/2017 1:06 AM
[Int: String]になってるの全く気が付かなかった
Avatar
あらら💦元のコード修正しました。
1:33 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
1:34 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
keyPath acceptからグッと作りやすくなったと思ってたら標準で用意されるのかー
Avatar
4 月上旬の駆け込み Review 祭りの結果が続々と Accept されてる。
Avatar
omochimetaru 4/26/2017 1:37 AM
166,167ってまだ読んでないんですけどざっくりどんな話ですか?
1:37 AM
言語機能としてシリアライズが付く?
Avatar
そう、で、json周りも標準採用
Avatar
omochimetaru 4/26/2017 1:38 AM
JSONもつくのね。珍しいな。
1:39 AM
そうなると細かいところがいろいろ気になるけどそれについては自分で読んでみます。ありがとう。
Avatar
任意のEncoder,Decoderプロトコルを定義出来るのだけど、JSONに関しては標準的な構造が用意されてる、と言うように見える
1:41 AM
plistもあるな
Avatar
(たぶん)3.1 で closure の inout まわりの inference が改善されてるんですね。 let ary1 = [1,2,3] let ary2 = ary1.reduce(into: []) { $0.append($1 + 12) } 非常によい。
✌ 1
2:11 AM
let dictionary = strings.reduce(into: [:]) { r, e in e.components(separatedBy: ":") => { r[$0[0]] = Int($0[1])! } } これも通った 😆
2:14 AM
あー、これだと dictionary: [AnyHashable: Int] になっちゃうのか。
Avatar
omochimetaru 4/26/2017 2:15 AM
$0が Array<String> 確定するから、$0[0]がStringになって String: Intになりそうだけど、保守的な推論になっちゃう? (edited)
Avatar
うそでした。 let dictionary = strings.reduce(into: [:]) { r, e in e.components(separatedBy: ":") => { r[$0[0]] = Int($0[1])! } } だと [String: Int]let dictionary = strings.reduce(into: [:]) { r, e in print(e) e.components(separatedBy: ":") => { r[$0[0]] = Int($0[1])! } } だと [AnyHashable: Int] single expression か否かで変わってくるみたいです。
Avatar
omochimetaru 4/26/2017 2:18 AM
print(e)で変わっちゃうんですか・・・微妙ですね。
Avatar
// If all properties are Codable, protocol implementation is automatically generated by the compiler: これ微妙な気が。
2:27 AM
Codable だった型にプロパティ足したときに気づかずに Codable でなくなってしまう危険があるのでは?
Avatar
omochimetaru 4/26/2017 2:28 AM
それはコンパイルエラーになるんでは?
Avatar
もし明示的に Codable をつけていれば、プロパティを足した瞬間に気付ける。 (edited)
Avatar
omochimetaru 4/26/2017 2:28 AM
使ってるところでCodableが期待されていてそれと衝突する
Avatar
使っているのが外部のモジュールだったら? (edited)
Avatar
omochimetaru 4/26/2017 2:29 AM
外部のモジュールがオブジェクトを受け取るところでCodableとして引数に受けてるから同じでは?
Avatar
ライブラリ AFoo が元々 Codable だったのを、まったく関係ない第三者が使っていて、ある日 Foo が突然 Codable でなくなるとかあり得る。
2:30 AM
しかも、最初から A の作者は FooCodable にするつもりはなかった、とか。
Avatar
omochimetaru 4/26/2017 2:30 AM
ライブラリAのFooにどうやってフィールドを追加するんですか?
Avatar
: Codable 宣言してなかったら Codable にならないんじゃないですか?
Avatar
え?そうなんですか?
Avatar
omochimetaru 4/26/2017 2:31 AM
Aの作者がFooをそうと意識せずにCodableにしている場合か。Aの内部ではCodableを使ってないなら、たしかに困る (edited)
Avatar
implementation が生成されるだけで : Codable は必須ってことか。
Avatar
omochimetaru 4/26/2017 2:31 AM
なんだ
Avatar
@omochimetaru Structural subtyping vs Interface みたいな話になるんじゃないかと思った。
Avatar
omochimetaru 4/26/2017 2:33 AM
まさにそれそのものですね。
Avatar
enum (without associated values)が自動的に Hashable になるのとは違う気がします。
Avatar
omochimetaru 4/26/2017 2:34 AM
ライブラリAの作者Pがenum Eを作っていて、それをユーザーQが辞書のキーに突っ込んでいる時
2:34 AM
PがEにassoc valを付け足すと、ユーザーQのコードが壊れるのか。
Avatar
それはあり得ますねー。
Avatar
omochimetaru 4/26/2017 2:35 AM
知らなかった
Avatar
同じく知りませんでした。
Avatar
omochimetaru 4/26/2017 2:35 AM
未然回避した
Avatar
やっぱ暗黙的に何かを満たすみたいなのはよくない気がする・・・。
2:36 AM
やるなら Structural subtyping までやっちゃう哲学じゃないとどっち付かずで中途半端感が。 (edited)
Avatar
omochimetaru 4/26/2017 2:36 AM
Structural Subtypingで通しても同じように崩壊するだけじゃないのかなあ。 (edited)
Avatar
Go や Crystal やダックタイピングやってる言語は崩壊してるってこと?
Avatar
omochimetaru 4/26/2017 2:37 AM
ライブラリAのFooが何かを満たしていることを永遠に保証できない
2:37 AM
そういうことです
2:37 AM
Rubyはそれが実行時エラーになるCrystalといえるけど
2:37 AM
実際のところドキュメントで
2:37 AM
このクラスはこのインターフェースを満たすっていうのを
2:37 AM
HTMLで書いてるんですよ
Avatar
いや、もちろん問題が起こる可能性はあるんだけど、それを前提にして回ってるわけで、それによって得られてるメリットもあるわけで、そっちを優先するという立場があってもおかしくはない。 Swift にはなじまないと思うけど。
Avatar
omochimetaru 4/26/2017 2:38 AM
あ、違うか、継承は実在するのか
2:39 AM
[PARAM] path: 文字列、または類似のオブジェクトを与えます。 実際には to_str に反応するオブジェクトなら何でも構いません。
2:39 AM
例えばこれとかなんですけど、これって、Swiftできちんと考えると
2:39 AM
class Pathname { init<P: ToStrProtocol>(path: P) { ... } }
2:40 AM
ようするにこういうシグネチャなんですけど
2:40 AM
今ユーザーQがライブラリAの型Fooをこれに渡してる時、
2:40 AM
このToStrProtocolは静的検査されないんで、 ライブラリAがアップデートでそれを削除した瞬間に
2:40 AM
実行時エラーが潜伏することになる
2:40 AM
Crystalならコンパイルエラーになる
2:41 AM
「to_strなんか消さないだろ」みたいなコンセンサスをみんなが守ってるから壊れない。
2:43 AM
そっちを優先するという立場があってもおかしくはない。
それはそうだけど、「徹底しないといけない」理由はよくわからないです。少し入れるのも完全に入れるのも、入ってくるメリットとデメリットが同時に増大するかどうかの違いで、同じことに思います
Avatar
はい、ぶっ壊れるのはわかるんだけど、それを前提に書き心地を優先して Structural subtyping をとるっていうのは、メンテナビリティと書き心地のトレードオフだから、後者を取る立場があってもおかしくはない。
2:43 AM
うーん、程度問題で、 Structural subtyping は許せないけど auto の Hashable は許せるってこと?
Avatar
omochimetaru 4/26/2017 2:43 AM
かき心地のトレードオフっていうのもよくわからないんですよね。このHTMLを日本語で書くの、かき心地いいのかな
2:44 AM
ドキュメント化した時点で矛盾してるような気がしています
Avatar
ドキュメント化しないスクリプトみたいなのが大量に生成されてるんじゃない?
Avatar
omochimetaru 4/26/2017 2:44 AM
それならわかる
Avatar
そういうときに implements Foo とか書きたくないと。
Avatar
今回の enum (without associated values)が自動的に Hashable になるけど、 CodingKey には自動的にはならず opt in ってのは統一感ないのはありますね。
Avatar
ですねー。 Swift は明示的なインターフェースを選んだ言語なわけだし、自動 Hashable は違和感がありますね。
Avatar
omochimetaru 4/26/2017 2:45 AM
simple enumとでも言えば良いのかな、全行読まないとそれが確定しないのユーザーにとって不便ですね
2:47 AM
C++もデフォルトでいろいろやる仕様から始まって、 そのデフォルト生成挙動を把握しろっていうプラクティスが普及して、 デフォルト生成を抑制する構文が追加されて、 デフォルト生成を明記する構文が追加されて、 カオス
2:48 AM
昔に定義された「デフォルト挙動」のせいで、「デフォルト禁止構文」と「デフォルト明示構文」が後から足されて安定した設計に至る話、複数ありそう
Avatar
Swift だとそこで過去を断ち切って非互換アップデートしちゃうからw
Avatar
omochimetaru 4/26/2017 2:49 AM
特にデフォルト明示構文が使われてるときのシュールさがやばいんですよね、わかるんだけど。
Avatar
@nonescaping みたいに
Avatar
omochimetaru 4/26/2017 2:49 AM
たしかに・・・
Avatar
Swift は @objc のデフォルト挙動を無くして 明示の方向に進んでるけど enum: Hashable を無くす議論はまだ無いですね。影響でかすぎるか。
Avatar
omochimetaru 4/26/2017 2:50 AM
いけるいける
Avatar
あー誤解してた。 associated value が Hashable の場合も自動的に、なのかと思った。
enum (without associated values)が自動的に Hashable
2:53 AM
うーん、まあ associated value なしの enum がありの enum に変化するのは、ぜんぜん違うものになってる感があるし仕方ない気も。 (edited)
2:54 AM
両方 enum で書けるってのが変かも?
Avatar
そもそもですねw
Avatar
omochimetaru 4/26/2017 2:54 AM
simple enum みたいな特殊キーワードとかもありかも
Avatar
Tagged union は enum じゃない気がするんですよね。
2:55 AM
enumerate できないし。
2:55 AM
enum じゃなくて union とかでもよかったのかも?
Avatar
omochimetaru 4/26/2017 2:56 AM
unionだとunion typeじゃないのに変な感じ
2:56 AM
C言語の union { } と紛らわしいし。
Avatar
でも今の状態も C の enum とかけ離れてない?
Avatar
omochimetaru 4/26/2017 2:57 AM
そうですねえ
Avatar
開発ツールに https://github.com/apple/swift/tree/master/tools/swift-api-digester ってのがあって、モジュールのAPIを出力してくれるツールで、 stdlib の 破壊的 API 変更をこれで監視しているんですが、これ的なものが SPM に組み込まれるとライブラリ開発者はなかなか助かるかもと思います。
swift - The Swift Programming Language
Avatar
おお
2:57 AM
それを元に自動でバージョニングしてくれるといいですね。
Avatar
omochimetaru 4/26/2017 2:57 AM
ほ〜〜
Avatar
API に変更がなければ patch を、互換性があれば minor を、非互換なら major を上げなさい、みたいな。
Avatar
↓ Swifty じゃなくないですか?引数の型は Encoder でなく T: Encoder であるべきでは? public protocol Encodable { /// Encodes `self` into the given encoder. /// /// If `self` fails to encode anything, `encoder` will encode an empty keyed container in its place. /// /// - parameter encoder: The encoder to write data to. /// - throws: An error if any values are invalid for `encoder`'s format. func encode(to encoder: Encoder) throws }
3:08 AM
↓じゃダメ? public protocol Encodable { func encode<T: Encoder>(to encoder: T) throws }
Avatar
norio_nomura 4/26/2017 3:15 AM
ジェネリックにしてしまうと、ランタイムでの差し替えが出来なくならない?プラグインとか。
Avatar
ジェネリック引数でできないのって具体的にどういうケースですか?
Avatar
norio_nomura 4/26/2017 3:18 AM
Objective-CでのEncoder実装とか?
Avatar
omochimetaru 4/26/2017 3:21 AM
それはジェネリックかどうかではなく、 swiftで定義されてる Encoder protocolが、@objc 互換かどうか、によって決まると思う
Avatar
norio_nomura 4/26/2017 3:22 AM
Encoder にはジェネリックメソッドありますね。じゃあ想定されていないのか。
Avatar
SE-0166 は Java の Serializable とは違って、シリアライズするための抽象的な仕組みを提供するだけなのか。素晴らしい。
Avatar
norio_nomura 4/26/2017 3:28 AM
What's in this pull request? This PR integrates preliminary work in introducing a new Swift-focused archival and serialization API as part of the Foundation framework. This PR focuses on what is av...
Avatar
SE-0167 読んでないですけど、多分 JSONEncoder は標準ライブラリじゃなくて Foundation ですよね? (edited)
Avatar
norio_nomura 4/26/2017 3:31 AM
ですです。
3:31 AM
This implements the JSONEncoder, JSONDecoder, PropertyListEncoder, and PropertyListDecoder types proposed by SE-0167. This pulls all Foundation-specific work out of #8124 for separate integration. ...
Avatar
JSONEncoderJSONSerialization で実装するのおもしろいですね。
Avatar
norio_nomura 4/26/2017 3:33 AM
レイヤー的には Himotoki とかと変わらないわけだ。
Avatar
ですね。でも decode/encode のコード書かなくていいのうれしい。
3:34 AM
Realm とかもこれに準拠することになるのかな?
3:35 AM
Swift 4 出たらこれ使って、 SwiftPM 対応の軽量 DB 書いてみようかなぁ。ずっとほしいと思ってるけど、シリアライズ部分が微妙で思いとどまってる。
Avatar
jsonのキーと合わせるのはkeyPathで出来るのかな
3:35 AM
capitalCaseとかsnake_caseとか、吸収してくれる感じならサイコーだ
Avatar
norio_nomura 4/26/2017 3:41 AM
This implements the JSONEncoder, JSONDecoder, PropertyListEncoder, and PropertyListDecoder types proposed by SE-0167. This pulls all Foundation-specific work out of #8124 for separate integration. ...
Avatar
jsonのキーと合わせるのはkeyPathで出来るのかな
CodingKey でやらないと駄目だと思います。 caseの吸収するなら コンパイラの自動生成に頼らずに自前でCodingKey型作って init(from decoder: Decoder) throws 実装しないとだめっぽいですね。
Avatar
なるほど
Avatar
norio_nomura 4/26/2017 4:14 AM
Mirror使ってシリアライズのデフォルト実装とか少し試してたけど、SE-0166 を待ちたくなった。
Avatar
Mirror 使いたいケース大分減りそうですね。
Avatar
減りますね
4:22 AM
後はOptionalをAnyに入れてしまった、ぐらいだろうか
4:28 AM
なんで let a: Int? = 42 let b: Any = a let c: Int? = b as! Int? はだめなのに enum Box<T> { case value(T) } let x: Box<Int> = .value(42) let y: Any = x let z: Box<Int> = y as! Box<Int> はできるんですか?
Avatar
as! がオプショナル周りで変なことしてるからだと思います
Avatar
(x as? Foo)! 扱いとか? (edited)
Avatar
SE-166 でどうしてもわからないのが サブクラスのデコードの扱いなんですが、 class Base : Decodable { } class Concrete : Base { } struct Foo : Decodable { let obj: Base public init(from decoder: Decoder) throws { self.obj = /* ???? */ } } どうやってデコードするのだろう。 (edited)
Avatar
それは encoder 次第?
Avatar
encode 時に obj のタイプ情報を一緒にエンコードしておくって事ですよね?
Avatar
omochimetaru 4/26/2017 4:32 AM
@koher ここらへんかなあ、Optionalが絡む as! について分岐がある Expr *visitForcedCheckedCastExpr(ForcedCheckedCastExpr *expr) { https://github.com/apple/swift/blob/3d178be169dd42b85f505ee1502232610535e4a3/lib/Sema/CSApply.cpp#L3491
swift - The Swift Programming Language
Avatar
じゃないですかね〜?
4:34 AM
@omochimetaru そのコード 7780 行もあるんだけどw
Avatar
この間の変性の話の続きなんですが
4:38 AM
Decoder<Base>にそれが必要な気がする (edited)
4:40 AM
で、Baseに関して
4:41 AM
struct Foo<B: Base> : Decodable { let obj: B public init(from decoder: Decoder) throws { self.obj = /* ???? */ } } こうするんじゃないかしら (edited)
Avatar
Foo<Base> だとしても Concrete のインスタンスは持てるから、解決できない気がします。
Avatar
あーー
4:45 AM
エンコード時にロストしてしまう
4:45 AM
確かに
4:46 AM
うーん、でも、それは明記された型の範囲でエンコードするのが責任の範囲な気もする
Avatar
Baseopen には出来ないってことですよね。
Avatar
subclassを作るときに、デコード/エンコードの処理を書くことを強制させる仕組みがあれば (edited)
4:48 AM
openに出来る?
Avatar
https://github.com/apple/swift-evolution/blob/master/proposals/0166-swift-archival-serialization.md#inheritance この項をみると class Base : Codable { let color: Color } class Concrete : Base { let name: String } みたいなのがあったときに { name: "FOOBAR" super: { color: "#abc109" } } みたいにエンコードされるように読めて、
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
あーーー
4:55 AM
なるほど、なるほど、
Avatar
container.decode(Concrete.self, forKey: .obj) じゃないとデコードできないのはあきらか。
Avatar
ですね
4:56 AM
だから、エンコーダーは、型の定義がBaseの型ならBaseとしてしかエンコードしてはいけないはず。 (edited)
4:58 AM
public protocol Encodable { /// Encodes `self` into the given encoder. /// /// If `self` fails to encode anything, `encoder` will encode an empty keyed container in its place. /// /// - parameter encoder: The encoder to write data to. /// - throws: An error if any values are invalid for `encoder`'s format. func encode(to encoder: Encoder) throws } この生え方だと、自身の宣言がBase型かConcrete型かの区別つかない気がする (edited)
5:01 AM
public protocol Encodable { /// Encodes `self` into the given encoder. /// /// If `self` fails to encode anything, `encoder` will encode an empty keyed container in its place. /// /// - parameter encoder: The encoder to write data to. /// - throws: An error if any values are invalid for `encoder`'s format. staitc func encode(to encoder: Encoder, instance: Self) throws // <- staticなら宣言されてる型から取れる } これなら整合性が取れるかな?
5:02 AM
それとも、実際にはBase.encode: (Base) -> (Encoder) throws -> () を使っていて問題なく動くのだろうか
Avatar
たぶんこんな感じになるんだけど struct Foo : Decodable { let obj: Base public func encode(to encoder: Encoder) throws { let objType: ObjType switch self.obj { case is Concrete: objType = .concrete //... default: objType = .base } container.encode(objType, forKey: .objType) container.encode(obj, forKey: .obj) } public init(from decoder: Decoder) throws { objType = container.decode(ObjType.self, forKey: .objType) let ObjT : Base.Type switch { case .concrete: ObjT = Concrete.self // ... case .base: ObjT = Base.self } self.obj = container.decode(ObjT, forKey: .obj) } } (edited)
Avatar
これだとBaseはopenにできないですね
Avatar
そうなんですよね。
5:08 AM
@objc なら NSClassFromString NSStringFromClass でなんとか.
Avatar
struct Foo<B: Base> : Decodable { let obj: B public func encode(to encoder: Encoder) throws { B.encode(obj)(encoder) } public init(from decoder: Decoder) throws { self.obj = B(from: Decoder) } } これなら、宣言の外の情報は破棄されますが、Bはopenにできそう。
Avatar
マージされたらいろいろ触ってみます。
5:13 AM
class Foo { func foo() { print("Foo") } } class Bar : Foo { override func foo() { print("Bar") } } Foo.foo(Bar())() // -> "Bar" なんで、 なかなか厳しいです。
Avatar
ゲーッ
5:14 AM
encodeをstaticにしないと危険だ
Avatar
let obj: Foo = Bar() Foo.foo(obj)() これでもいっしょ。
Avatar
class Foo { class func encode(obj: Foo) { print("Foo: \(obj)") } } class Bar: Foo { override class func encode(obj: Foo) { print("Bar: \(obj)") } } Foo.encode(obj: Bar()) // Foo: __lldb_expr_.Bar
5:16 AM
こっちですかねぇ
5:17 AM
overrideで引数のFooが書き換えられない…
5:17 AM
ダメな気がしてきた
Avatar
norio_nomura 4/26/2017 5:34 AM
BaseCodable でなければ、型が失われるのは必然に思える。
Avatar
protocol Encodable { static func encode(obj: Self) } class Foo: Encodable { class func encode(obj: Foo) { print("Foo: \(obj)") } } class Bar: Foo { class func encode(obj: Bar) { print("Bar: \(obj)") } } Foo.encode(obj: Bar()) // Foo: Bar.encode(obj: Bar()) // Bar: func encode<E: Encodable>(type: E.Type, obj: E) { E.encode(obj: obj) } encode(type: Foo.self, obj: Bar()) // Foo: encode(type: Bar.self, obj: Bar()) // Foo: いけるかと思ったけどダメだった
5:35 AM
変性周りが蔑ろなのなんとかしないと壁を超えられない気がする
5:36 AM
でなければ、classは割りを食うことになりそう…
Avatar
norio_nomura 4/26/2017 5:38 AM
あいや Base: Codable か。
5:41 AM
DerivedConformanceCodable.cpp とかあるから、コンパイラの自動生成が頑張ってくれると期待。 https://github.com/apple/swift/pull/9004/files#diff-9ceab8e46e5cb79b6cf990fe2b464e21
What'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 combined into o...
5:42 AM
ジェネリックなサブクラスのテストケースとか見当たらないのは心配だけど。
Avatar
norio_nomura 4/26/2017 6:57 AM
Development Snapshotをちょっと使ってみたのだけど、 extension Sequence { fileprivate func grouped<U: Hashable>(by transform: (Iterator.Element) -> U) -> [U: [Iterator.Element]] { return reduce([:]) { dictionary, element in var dictionary = dictionary let key = transform(element) dictionary[key] = (dictionary[key] ?? []) + [element] return dictionary } } }console.log error: redundant conformance constraint 'U': 'Hashable' fileprivate func grouped<U: Hashable>(by transform: (Iterator.Element) -> U) -> [U: [Iterator.Element]] { ^ note: conformance constraint 'U': 'Hashable' inferred from type here fileprivate func grouped<U: Hashable>(by transform: (Iterator.Element) -> U) -> [U: [Iterator.Element]] { ^ なんてエラーが出るようになったのね。
6:59 AM
戻り値が [U: [Iterator.Element]] だから U: Hashable は要らない。
Avatar
かしこい
7:19 AM
これ今ガリガリwhere句書いてるの大幅に削れる
Avatar
結局、SE-0166の public protocol Encodable { func encode(to encoder: Encoder) throws } が↓でない理由ってよくわからないままですっけ? public protocol Encodable { func encode<T: Encoder>(to encoder: T) throws } swift-evolutionとかで聞いてみたらいいのかな?
Avatar
encoderは任意のパスから任意の型を取り出せる抽象であれば良いので、ジェネリックスにする必要は無いのだと思います
1:33 AM
ああ、それはデコーダーだ
Avatar
どっちでもいいならジェネリックメソッドにした方が静的ディスパッチになって速いですよね?
Avatar
あーそれは確かに
Avatar
Swift の標準ライブラリってあまりプロトコル型で引数をとらない印象があったので違和感を感じています。印象だけかもしれませんが。
1:35 AM
DB から大量に読み込みとか考えると繰り返し実行されるから、動的ディスパッチのオーバーヘッドが効いてきそう・・・。(それは decode だけど、同じ話として) (edited)
Avatar
型消しの言語機能化入るのと関連して、protocol周りを暗黙的にGenerics扱いにする隠し球がくる、とかでしょうか
1:37 AM
高望みしすぎかなw
Avatar
「型消しの言語機能化」って Generalized existentials のことですよね?
Avatar
はい
1:38 AM
名前を覚えきれない😫
Avatar
はい、僕も今ググって確認しましたw
1:40 AM
あれって抽象のまま保持しないといけないこともあるし、最適化できない気がするんですよねぇ。というか、最適化できるケースはジェネリック関数/メソッドでいいわけで、それじゃできないことをするときに Generalized existentials を使うことになるんじゃないですかねー?
Avatar
あ、いや
Avatar
という関連で、「暗黙的にGenerics扱いにする」も厳しそうな?
Avatar
Genericsな引数として入ってきたprotocolを、変数に格納するときに関連がありそうだな、と
1:42 AM
素protocolで宣言された引数は、そのままGenerics扱いにしてしまっても問題なくなるかしら?と思ったのです
1:42 AM
(そんなに考えてない)
Avatar
うーん、コーナーケースで問題が出そうな気も?
Avatar
例えば今適当にprotocolで宣言した引数をGenericsに変更して困る事って
1:44 AM
Optionalなどのモナドに包んで推論不可能になることだと思うんですよね
1:44 AM
うーん、でもこれは関係ないか
Avatar
(SomeProtocol) -> SomeProtocol みたいな型の変数に入れるためには抽象のままじゃないといけないけど、関数コールしてる箇所はジェネリック扱いすればよさそうだし、何かあるかな・・・。
Avatar
返り値protocolは、受け手側が具体型じゃないんで、推論不可能
1:45 AM
あー
1:46 AM
そうか、protocolな型を受け取ってそれをそのまま渡す、
1:46 AM
あり得ますね
1:46 AM
これは困る
Avatar
んーでも、 Foo: SomeProtocol があったとして、 func bar<T: SomeProtocol>(_ x: T) -> T { return x } let foo: SomeProtocol = Foo() let foo2: SomeProtocol = bar(foo) のように bar がジェネリック扱いでも問題ないですよね?
Avatar
それはそうなんですが
Avatar
まあ、暗黙ジェネリック化はちょっとやりすぎでなさそうな気がします。何か問題起こりそうだし。
Avatar
それが可能になるためには、全てのprotocol型変数が言語機能によって、型消し相当の具体型に昇華してないといけない
1:50 AM
でもそれが可能なら、全てのprotocol型をGenerics扱いに出来そうだ
Avatar
あ、↓はダメだ。ジェネリック化できない。 func foo(x: Foo<SomeProtocol>) -> Foo<SomeProtocol> { ... } (edited)
1:51 AM
func foo<T: SomeProtocol>(x: Foo<T>) -> Foo<T> { ... } にしたら、 FooT について covariant じゃないから戻り値の型に互換性がなくなっちゃう。
Avatar
func foo<T: SomeProtocol, U: SomeProtocol>(x: Foo<T>)->Foo<U>ですよね元のものは (edited)
1:52 AM
その上で、SomeProtocolで宣言されたものが型消しになるのなら、Okだと思います (edited)
Avatar
↓だとできないですね。 func foo(x: Int) -> SomeProtocol { switch x { case 0: return Foo() case 1: return Bar() case _: return Baz() } }
Avatar
そう。その場合はSomeProtocolが、型消し扱いの具体型になる
1:55 AM
その扱いなら、Generics化が出来ると思います
Avatar
AnySequence 的な型を使えばってことですか?
Avatar
はい
1:56 AM
protocolで宣言された変数がAnyProtocolになって、
Avatar
そもそもよく考えたら、↓をジェネリック化しても大丈夫と主張してるということは、それが真ならこういうケース(引数だけプロトコル型)では自動ジェネリック化も問題を起こさないはずですね・・・。 public protocol Encodable { func encode(to encoder: Encoder) throws }
Avatar
そうですねw
Avatar
そう考えれば自動ジェネリック化もなくはない?
1:58 AM
もしくは、↑をジェネリック化して問題が起こるケースがあるかなぁ・・・。
Avatar
ちょっとまだ考えきれてないんですが、自動Generics化で、推論周りで破綻しないかな、破綻がなければ大丈夫
2:00 AM
Protocol?でnilが推論不可能なのも、AnyProtocol?.noneということにすればよくて
2:00 AM
型パラが必要で推論できない場合も、代表的な具体型を差し込めば良さそうだ
Avatar
うーん、やっぱ Any よくない気がする・・・。
Avatar
そして、Anyがprotocol<>の型消しに帰結する、と、しなきゃいけない
2:01 AM
うーん
Avatar
値型とサブタイピングは相性悪いですね・・・。
2:02 AM
プロトコル型が witness table 使わなきゃいけないのと同じように、 Any にも気持ち悪さを感じる。
2:03 AM
プロトコル型変数も Any も禁止とかしたら、さすがに無理かなぁ。どうしても Any にせざるを得ないケースもあるしなぁ。
2:04 AM
参照型と、参照型とみなせるイミュータブルな値型なら問題ないと思うけど。 (edited)
Avatar
いや、Anyがprotocol<>の型消しであると言う解釈で良ければ
2:04 AM
普通にありえますね
Avatar
でも OptionalAny の問題は値型関係ないか・・・。
Avatar
今思い付く限りでは、Generics化は成り立つんですが、現実的なコンパイル時間に収束するかが全く予想できない
Avatar
でも、最初からジェネリック関数/メソッドだったら大丈夫なわけですよね?暗黙的にオーバーロードされてるという解釈なら問題ないのでは?
Avatar
それはそうですね
2:07 AM
今ちょっと考えてるのは
2:08 AM
protocol型変数を持つ型を、Generics型に昇華出来ないか、と言うことを考えてました
2:08 AM
ちょっと厳しそう
Avatar
それは難しいと思います。
Avatar
protocol型引数が、inoutなのはあり得るんでしたっけ
2:09 AM
これがokだとGenerics化は破綻しそう
Avatar
struct Foo { var bar: BarProtocol }struct Foo<Bar: BarProtocol> { var bar: Bar } にしてしまうと、 extension Int: BarProtocol {} extension String: BarProtocol {} var a = Foo(bar: 123) let b = Foo(bar: "xyz") a = b の最後の行ができなくなってしまう。
Avatar
ですね
2:12 AM
変数は無理と言うかおそらく意味がない、同じ理屈でinoutな引数もダメなはず
Avatar
なので、変換可能なのは、純粋なプロトコル型引数のみの場合ですね。
2:12 AM
inout は引数でもあり戻り値でもあるので、戻り値の場合と同じかと思います。
Avatar
そうすると、1つの型にTとUを重ねるのは無理なので
2:13 AM
これも出来ませんね、かなしい
2:16 AM
inoutを引数と返り値に分解して解釈する過程で差し込めば大丈夫なのかな
2:17 AM
それはさておき、Encoderはジェネリックスじゃないのは気になりますね
Avatar
そうですねぇ。
Avatar
omochimetaru 4/27/2017 2:18 AM
上の方しか読んで無いけど
2:18 AM
型のパラメータでも
2:18 AM
特殊化はされると思う
2:19 AM
encodeを呼び出すときにレシーバーの型が見えてれば。
Avatar
ん?特殊化されるジェネリック関数でなく、プロトコル型引数になってるのはなぜ?って話。
Avatar
omochimetaru 4/27/2017 2:19 AM
encodable.encodeにおいてencoder Eが
2:20 AM
encodable<E>.encodeとなるか encodable.encode<E>となるか
2:21 AM
の違いで、速度的な話なら、前者でも特殊化はされると思うから、同じだと思う
Avatar
Encodableは別にEncoderを型パラとして定義はしていない
Avatar
omochimetaru 4/27/2017 2:22 AM
あれ?そうなのか、勘違いだ
Avatar
任意のEncoderに対してencode関数が使える、というだけ。
Avatar
omochimetaru 4/27/2017 2:22 AM
Encoderはただのプロトコル?
Avatar
omochimetaru 4/27/2017 2:22 AM
assoc typeかと思った。
Avatar
そこがミソ
Avatar
omochimetaru 4/27/2017 2:23 AM
あれ、じゃあ、
2:23 AM
assoc typeの無いプロトコルを
Avatar
なので、Encodableなら、その瞬間にJsonもplistもprotobufも使える
Avatar
omochimetaru 4/27/2017 2:23 AM
ジェネリックでないアレでexistebtialでうける形になってるのか
2:24 AM
だとするとその場合でも特殊化されるのかな・・・?
Avatar
それは、protocol型引数を暗黙的にGenerics化できるということ、そして上の議論
Avatar
omochimetaru 4/27/2017 2:26 AM
method<X:P>(x: X)と method(x:P) Pにassoc tyがない場合にはどちらでも書けるがコンパイル結果がどう変わるか
2:26 AM
というのがコアな謎か。
Avatar
そうね、僕の議論はそこにさらに
Avatar
omochimetaru 4/27/2017 2:26 AM
うん(続きはまだ読んで無かった
Avatar
Generalized existentialsがあれば、成り立つようになるのでは(直感)ってやつ
2:27 AM
associatedtypeありでも。
Avatar
omochimetaru 4/27/2017 2:28 AM
GEがあればアソックありでも同じ議論ができると思うよ。
Avatar
norio_nomura 4/27/2017 2:28 AM
func encode(to encoder: Encoder) throws は自動生成されるというのがポイントのような気がします。 (edited)
2:29 AM
PRの自動生成している箇所 https://github.com/apple/swift/pull/9004/files#diff-9ceab8e46e5cb79b6cf990fe2b464e21R407 // @derived func encode(to encoder: Encoder) throws {
What'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 combined into o...
Avatar
omochimetaru 4/27/2017 2:30 AM
コンパイラに自動生成タイミングがあるから、普通のやつと違って、特別に特殊化をしこむ余地とかがあるかもって事ですか?
Avatar
norio_nomura 4/27/2017 2:32 AM
この @derived というキーワードを apple/swift リポジトリで探すと、 enumEquatable, Hashable, RawRepresentableError_nsErrorDomain などで使われてて、それらは全部ジェネリックでは無い。
2:33 AM
ジェネリックなメソッドを自動生成するのを避けているのかな?と。
Avatar
omochimetaru 4/27/2017 2:35 AM
ふむ。他もそうなってるんですね。
Avatar
norio_nomura 4/27/2017 2:37 AM
ジェネリックの方が良い悪い、ジェネリックでは出来ないケースがある、とかではなく、実装上の理由なのかな?と。
Avatar
omochimetaru 4/27/2017 2:37 AM
なるほど。
Avatar
norio_nomura 4/27/2017 2:38 AM
まあ、PRにコメント書いて聞くのが早い気がしますが。 (edited)
Avatar
func encode(to encoder: Encoder) throws このメソッドって、実際には基本的に外部ライブラリであるエンコーダーから呼ばれるわけで、specialize しようがないと思うんですけど違います?
2:50 AM
encode<T: Encoder>( でだめな理由は無いけど、そうする意味もないのでは?ということです。 (edited)
👍 1
Avatar
自動生成されたencodeが、自身が持つフィールドのencodeを呼ぶことは無いのかな
2:51 AM
それがあるとGenericsにする価値がありそうです
Avatar
omochimetaru 4/27/2017 2:55 AM
let farm = Farm(name: "Old MacDonald's Farm", location: Location(latitude: 51.621648, longitude: 0.269273), animals: [.chicken, .dog, .cow, .turkey, .dog, .chicken, .cow, .turkey, .dog]) let payload: Data = try JSONEncoder().encode(farm) 使い方がこうだから、JSONEncoderが内部でfarmのencodeメソッドを呼ぶのか。
Avatar
基本的に外部ライブラリであるエンコーダーから呼ばれるわけで、specialize しようがない
標準ライブラリのジェネリック関数は標準ライブラリ外から呼んでも specialize されますよね?外部だと specialize できないというわけでもない気が。 @_specialize とかもありませんでしたっけ?
Avatar
omochimetaru 4/27/2017 2:56 AM
マジか
Avatar
@_specialize はライブラリ側につけるのか。
Avatar
omochimetaru 4/27/2017 2:57 AM
そんな謎技術があったのか。
2:57 AM
bitcodeとかってそういうところで活躍してんのか?
Avatar
norio_nomura 4/27/2017 2:57 AM
bitcodeは無関係かと
Avatar
omochimetaru 4/27/2017 2:58 AM
あら。。 (edited)
Avatar
外部でも利用側からリンクするときに specialize されたバイナリを吐けばいいから原理的にはできそうな気が? (edited)
Avatar
omochimetaru 4/27/2017 2:59 AM
JSONEncoderのencodeメソッドの中で、引数で受けたEncodableのencode(encoder)を呼ぶ部分はどうしようも無いですよね
Avatar
ライブラリ外から呼んでも specialize されますよね?
呼び出し側をコンパイルするときはそうですが、この場合呼び出し側であるエンコーダーをコンパイルするときには何も分からないし、func encode をコンパイルするときに encoder が JSONEncoder であるか否かはわからない。
(edited)
3:01 AM
@_specialize(where T == JSONEncoder) func encode<T : Encoder>(to encoder: T) throws { ... } ってしとけばいいかもしれないけど、使っちゃ駄目
Avatar
encode をコンパイルするときは specialize されてない抽象の状態でコンパイルし、呼び出し側をコンパイルするときに encode の specialize 版を生成することはできないですか?
Avatar
norio_nomura 4/27/2017 3:02 AM
それが出来るなら @_specialize は存在しないのでは (edited)
Avatar
現段階での挙動ではなく、理論上可能かどうかという意味でです。
3:04 AM
たとえば、 encode のバイナリにリビルドするのに十分な付加情報を埋め込んでおけば(バイナリ化されたASTとか)リンク時に specialize することはできるはずです。
3:06 AM
そこまでしなくても、プロトコル型引数が抽象表現されているはずなので、それを specialize することってできそうな気がするんですが無理なんでしょうか?ローレベルに詳しくないので想像の話ですが。
Avatar
norio_nomura 4/27/2017 3:06 AM
つまり、stdlibとか全部を含めて whole module optimization する的な話ですか?
Avatar
呼び出し側って ここで言うと 例えば JSONEncoder なので func encode をコンパイルする前に既にライブラリとしてコンパイルされているという認識なんですけど、それは良いですか? (edited)
Avatar
はい、それはよいです。
3:08 AM
コンパイル済みのものを解析して、抽象表現されている部分だけを specialize するのは無理?
3:08 AM
あれ?機械語まで落ちてるのか。
3:09 AM
LLVM レベルでとまってる気がしてたけど、
Avatar
MyType.encode をコンパイルするときに、 specialize 出来たとして、 呼び出し側がその specialize された メソッドをどうやって呼ぶのか想像がつかないです。 (edited)
Avatar
omochimetaru 4/27/2017 3:10 AM
LLVMIRのレベルでも型情報はなくなってますよ
Avatar
じゃあそもそもの話として、GenericsTypeとGenericsFunctionは全然違うのか
Avatar
omochimetaru 4/27/2017 3:12 AM
@tarunon いや、GenericsFunctionは、外部リンクするように抽象的な版のバイナリを吐いていて、抽象的な版はその場限りなGenericsTypeを引数に受けるような挙動ではある
Avatar
型パラはあるけど、中身では具体型として扱えるものではない、ということ
3:14 AM
つまり、<Foo: Protocol>(foo: Foo)においてFooは具体的な型パラだが、fooはProtocol型変数と変わらない状態?
Avatar
omochimetaru 4/27/2017 3:21 AM
回答を書こうとしてるけど曖昧なところが出てきたからちょいまち
Avatar
specialize 云々は抜きにして、前言撤回します。 func foo<T: Encoder>(to encoder: T) の方が良い。
3:26 AM
理由書いてるけどちょっとまってくださいー
Avatar
今って、標準ライブラリのジェネリック関数/メソッドについては外部からコールしても specialize されると思うんですがなぜですか?標準ライブラリだからできる芸当?
3:27 AM
public struct Foo<T> { private let array: [T] public init(array: [T]) { self.array = array } public func map<U>(_ transform: (T) throws -> U) rethrows -> Foo<U> { return Foo<U>(array: try array.map(transform)) } public var count: Int { return array.count } }
Avatar
omochimetaru 4/27/2017 3:27 AM
@tarunon LLVMIRではジェネリックな関数の引数は、 (x, wt, xt) な 3つの引数に展開されてて x: Catなどの具体的な型の値へのポインタ wt: xとセットで使える、Protocolのメソッド定義に準拠したwitness-tableへのポインタ xt: xの元々の型 Cat の 型の型へのポインタ で呼び出されるようになってる。 で、wtからメソッドを引っ張ってくると、 引っ張ってきた関数ポインタは、(x, xt) を受け取るようになっていて、 その関数の内部で、 xに対して Cat に定義されてた本物のメソッド呼び出しがされる。
Avatar
Array.map は specialize されてるっぽい
Avatar
omochimetaru 4/27/2017 3:29 AM
xtの使い所は、 例えばプロトコル型のままコピーとかしてるときに、 値のコピー自体が、xtから取り出された「コピー用の関数」に x を渡す形にコンパイルされる。 これによって、Catがstructの場合は値コピー、classの場合は参照コピー + Retain , みたいな挙動が抽象化される
Avatar
public protocol BAR { func foo() } public func XXXXX<T : BAR>(arg: T) { arg.foo() } public func ZZZZZ(arg: BAR) { arg.foo() } -O -emit-ir 結果 https://gist.github.com/rintaro/8794ecd01e78e6b001fce192b07f2d7d#file-test-sil
Avatar
omochimetaru 4/27/2017 3:30 AM
つまり、<Foo: Protocol>(foo: Foo)においてFooは具体的な型パラだが、fooはProtocol型変数と変わらない状態?
で、 プロトコル型変数 (Existential) は、 (x, wt, xt)の 3 つのフィールドをもつ struct みたいなバイナリになるから、変わらないっちゃ変わらない
Avatar
@omochimetaru wtは、Fooへのテーブル?それともProtocol全般へのテーブル?
Avatar
omochimetaru 4/27/2017 3:31 AM
「Fooは具体的な型だが」については、実行時においては、 xt の形で保持されてる
3:31 AM
ちょっと話題がぶつかってるので #swift-2 で。
Avatar
@omochimetaru の言っている通りジェネリックな方は引数で型情報が渡ってくるので、直接その witness table にアクセス出来るけど、 後者は protocol 値からいろいろ情報抜き出さないといけない分だけ手数が増える。
Avatar
specialize 関係なくジェネリックな方が速いのか。
Avatar
ですね。
Avatar
omochimetaru 4/27/2017 3:39 AM
@rintaro AssociatedTypeが無いprotocolの場合は Protocol Existential 型の値になるけど、それが結局 (x, wt, xt)の3フィールドだから、情報抜き出すところは同じだと思います。
Avatar
norio_nomura 4/27/2017 3:43 AM
呼ぶ側/呼ばれる側のどちらが取り出すか、の違いではない?
Avatar
omochimetaru 4/27/2017 3:45 AM
protocol Hogeable { func hoge() -> Int } func callHogeableHoge(hogeable: Hogeable) -> Int { return hogeable.hoge() } ↑こういうのがあるとき、LLVMIRだと、↓こういう引数になってる。 (x, xt, wt) の3タプルになっている。 %P4main8Hogeable_ = type { [24 x i8], %swift.type*, i8** } define hidden i64 @_TF4main16callHogeableHogeFPS_8Hogeable_Si(%P4main8Hogeable_* noalias nocapture dereferenceable(40)) #0 { ... }
Avatar
SIL 的には open_existential_addr が入っているか否か。 https://github.com/apple/swift/blob/master/docs/SIL.rst#open-existential-addr
swift - The Swift Programming Language
Avatar
omochimetaru 4/27/2017 3:47 AM
protocol Fugable { typealias Element func fug() -> Element } func callIntFugableFuga<F: Fugable where F.Element == Int>(fugable: F) -> Int { return fugable.fuga() } ↑一方こういうのがあるとき、LLVM IR だと↓こうなる define hidden i64 @_TF4main18callIntFugableFugauRq_S_7Fugablezqq_S0_7ElementSi_Fq_Si(%swift.opaque* noalias nocapture, %swift.type* %F, i8** %F.Fugable) #1 { Existentialがないけど、結局、引数として x, wt, xt が並んでる。 (edited)
3:49 AM
あ〜たしかに
3:49 AM
xのサイズが24バイトを超えるかどうかとかで
3:49 AM
直接ペイロードがコピーされてるか 、ポインタ渡しになっているかとかが変わるので
3:49 AM
そこらへんの分岐が、SILのopen_existential_addrがLLVMになる時に
3:49 AM
直接のアドレス操作バイナリにコンパイルされる感じだけど
3:50 AM
間接の場合は引数渡しより遅くなりうるかも??
3:51 AM
あ、でも引数にバラける場合は常にopaqueポインタ渡しになるから、それと同じなのかな、うーん、わからない。
Avatar
@norio_nomura
呼ぶ側/呼ばれる側のどちらが取り出すか、の違いではない?
そうなんですが、呼ぶ側は通常 existential 型で値を持っているわけではないので、generic の場合 existential 型 を生成する必要がない場合がほとんどだと思うのです。
Avatar
omochimetaru 4/27/2017 3:54 AM
そうなんですが、呼ぶ側は通常 existential 型で値を持っているわけではないので、generic の場合 existential 型 を生成する必要がない場合がほとんどだと思うのです。
たしかに!これは同意です、cat型で保持していて、渡す時にプロトコルexistentialにアップキャストするのが代替だから、パック側のコストもありますね。
Avatar
norio_nomura 4/27/2017 3:55 AM
なるほど
Avatar
@koher
標準ライブラリのジェネリック関数/メソッドについては外部からコールしても specialize される
stdlib は特別らしいです。 https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#advice-put-generic-declarations-in-the-same-module-where-they-are-used
swift - The Swift Programming Language
Avatar
norio_nomura 4/28/2017 1:28 AM
だとすると Encoder のコードも Codable ごとに specialize されうるのかな。
Avatar
Foundation Swift モジュールも特別扱いの対象なら可能性あるかもしれないですね。
Avatar
@rintaro おお、ありがとうございます!
3:14 AM
SwiftPM でソースからビルドした場合はモジュールまたいでも specialize してくれるようになったりするとうれしいですねぇ・・・。
Avatar
どうも特別扱いは -sil-serialize-all っていうオプション付きでモジュールがコンパイルされているか否かによるみたいです。この場合、実装含めた全てのSILが .swiftmodule にシリアライズされるので、caller側はcalleeのSILレベルでの実装を見通して最適化が出来ようになると。
😮 1
3:17 AM
ためしに swift build -Xswiftc -Xfrontend -Xswiftc -sil-serialize-all でビルドしてみたら LLVM ERROR: Invalid abbrev number <unknown>:0: error: merge-module command failed with exit code 1 (use -v to see invocation) 😢
Avatar
お、それは現時点ではできなくても将来的にはできる可能性もあるのでは?
3:20 AM
それがありうるなら encode がジェネリックの方がいい強力な理由になるんですけどね〜。
3:22 AM
そう言えば、昨日言ってた @_specialize を使うべきでないという理由はなんですか?
Avatar
とりあえず encode については質問済みなので回答来たらまた。 https://github.com/apple/swift/pull/9004#pullrequestreview-35266665
What'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 combined into o...
Avatar
ありがとうございます!
Avatar
@_specialize について、 _ で始まるものは本当に使わないほうがいいです。意図的にやっているのかっていうくらい頻繁に仕様が変わります。
Avatar
こういう場合って、 PR でこっちの方がいいねってなったら、 Proposal と違った形で実装されたりするんですか?
Avatar
実質のインターフェイスが変わらない限り evolution 通さずに変更はあると思います。
Avatar
なるほど。
Avatar
@_specialize は実際 Swift3 と 現状の master でインターフェイス変わってます Swift3 @_specialize(Int, String) func foo<T, U>(x:T) -> U master @_specialize(where T == Int, U == String) func foo<T, U>(x:T) -> U
Avatar
@_specialize のインターフェースも変わってるんですね・・・
3:38 AM
@_specialize は代替手段がないから辛いですね。
3:38 AM
とはいえ、どうせ Swift はソース互換性ないからバージョンアップ時は一緒に直してしまえばいい気もw
Avatar
_開始は、マイナーバージョンアップですら保障されてない気がする
Avatar
普通の _Foo は使わないですが、 @_specialize は特殊なのかと思ってました。
Avatar
norio_nomura 4/28/2017 3:49 AM
ためしに swift build -Xswiftc -Xfrontend -Xswiftc -sil-serialize-all でビルドしてみたら
これ、シングルモジュールのパッケージならビルド出来ますね。
Avatar
norio_nomura 4/28/2017 4:00 AM
ビルドできるが、各ソース毎の中間 .swiftmodule は大きくなるけど、パッケージのは大きくならない。
Avatar
omochimetaru 4/28/2017 5:47 AM
どうも特別扱いは -sil-serialize-all っていうオプション付きでモジュールがコンパイルされているか否かによるみたいです。この場合、実装含めた全てのSILが .swiftmodule にシリアライズされるので、caller側はcalleeのSILレベルでの実装を見通して最適化が出来ようになると。
ほ〜〜〜〜〜〜
Avatar
omochimetaru 4/28/2017 7:13 AM
PR0166い途中まで読んでるけどこれめっちゃ頭いいな
7:14 AM
あるstructが:Encodableに準拠してるとき、
7:14 AM
自動的にプロパティ名と同じcase名をもったenumが定義されて
7:14 AM
そのオブジェクトをエンコードする時のコンテナ(JSON Object)とかにあたるオブジェクト
7:14 AM
に、型パラメータとしてCodingKeyが取れるおかげで
7:15 AM
プロパティ名に対応しないキーを間違って使っちゃう可能性が排除される
7:15 AM
public struct Location : Codable { private enum CodingKeys : CodingKey { case latitude case longitude } public func encode(to encoder: Encoder) throws { // Generic keyed encoder gives type-safe key access: cannot encode with keys of the wrong type. let container = encoder.container(keyedBy: CodingKeys.self) // The encoder is generic on the key -- free key autocompletion here. try container.encode(latitude, forKey: .latitude) try container.encode(longitude, forKey: .longitude) } }
7:17 AM
Encodercontainer メソッドが、 K.Type を引数で受けていて、 container の型パラに引き継がれる。 enum CodingKeysはstruct Locationのinner typeで、Locationのために自動定義されたやつだから、プロパティ名とキーが静的に結びつく
Avatar
omochimetaru 4/28/2017 7:58 AM
継承については 親クラス部分をまとめたオブジェクトを super キーにぶら下げるみたいですね
7:59 AM
{ "a": 3, "b": 2, "super": { "c": 1 } }
Avatar
omochimetaru 4/28/2017 8:58 AM
0167も見てるけど、エラー型に [CodingKey] がついて無さそうに見える。
8:59 AM
JSONが壊れてる時、ルートからみてどこが壊れてるのか、デコード時にパスがトレースされるんでそれを例外に保持して、メッセージに出したい
8:59 AM
レビュー期間とっくに終わってるしオシマイ
Avatar
CocoaError投げるみたいなこと書いてるなー
9:44 AM
Errorが役に立た無さそう
Avatar
omochimetaru 4/28/2017 9:44 AM
そのError型になんのassociated valueもないんだよねえ
9:45 AM
Encoder型自体は codingKeys: [CodingKey?] としてパスを保持してるから
9:45 AM
仕組み的にはできるはずなんだけども。
Avatar
Swiftのプロパティとinout参照を組み合わせたときの挙動が面白い on @Qiita https://t.co/pBDyCv6D89
10:37 AM
かいた
Avatar
https://github.com/apple/swift/blob/master/docs/OwnershipManifesto.md#the-law-of-exclusivity によりそういうコードが今後きちんと拒否されるかも。
swift - The Swift Programming Language
Avatar
そうですね、オーナーシップの展開は気になっていて、参照のことが気になって試していました
10:55 AM
この場合だとcatはMainの一部だから、参照をborrowしようとすると、catのborrowの間はMainが不正な状態になっているから、メソッドが呼び出せない?
10:56 AM
Catがクラスの場合でも記事の内容は成立すると思うけど、 その場合はどうなるんだろう。
Avatar
どう処理するのか全然予想がつかないw
Avatar
完全フロー解析すれば、updateIntにcat.ageをborrowしているケースがあるから、updateIntの中でcat.ageをリードするのは不正 って事になるのかな? でも外部モジュールとか跨いでいると無理そうですよね
Avatar
https://github.com/devincoughlin/swift/blob/master/test/SILOptimizer/exclusivity_static_diagnostics.swift とりあえず現状こんな感じのテストケースで実装済みです。
swift - The Swift Programming Language
Avatar
うお!このフォークで試せるんですか?
Avatar
master-enforce-exclusivity=checked つけると試せるです。
Avatar
おお。実はちまちま探してたんだけどそれっぽい実装ロジックが見つからなくてまだお試し実装無いのかと思ってました
11:03 AM
exclusivityってキーワードだったんですね どうやって追っかけているんですか?
11:03 AM
MLのOwnershipスレだけさらってたけど見つけられず。
Avatar
https://github.com/apple/swift/pulls 日常的に追っかけてるだけです
swift - The Swift Programming Language
Avatar
なるほど・・・
11:09 AM
ちょうどゴールデンウィークだし試してみます
Avatar
都合上両側にスペースを置きたくない演算子~~(lhs: Int, rhs: Int)について 1~~-2とかやるとコンパイル通らないので ~~-演算子を定義するという糞ハック
Avatar
norio_nomura 4/29/2017 3:14 AM
encode(to:) の理由を答えてくれてる。なるほど。 https://github.com/apple/swift/pull/9004#discussion_r114044478
What'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 combined into o...
Avatar
なるほど、すっかり忘れてました。これが通らないってこと。 protocol P { func foo() } struct S : P { func foo() { print("S.foo") } } func foo<T : P>(p: T) { p.foo() } let obj: P = S() foo(p: obj)
Avatar
あ、ですです
6:55 AM
これは通らない、通そうとすると、Pの宣言が全て暗黙的にtype-erasure相当の具体型ということにならないといけないはず
6:55 AM
或いは
6:57 AM
AnyかAnyObjectのように、Protocolのまま型パラに入れれるようにならないといけない。
6:57 AM
ところでなんでAnyとAnyObjectは型パラになれるんですか?
6:57 AM
nominaltype(でしたっけ?)と関係あるのかな。
Avatar
Any に関しては <T : Any> は何も書かないのと一緒扱いなのかな? Any = protocol<> でしたし、今もパーサー時点で Any を 空のコンポジションとして AST に入れている。 AnyObjectprotocol P : AnyObject protocol P : class と同義であるみたいに、 class レイアウトであること「だけ」を強制するものとして、コンパイラでの特別扱いがあるので、その絡みだと思いますが、よく分かんないですね。 (edited)
Avatar
なるほど、すっかり忘れてました。これが通らないってこと。
うーん、それはそうなんですが、まだ KeyedEncodingContainer をちゃんと読めてなくて、 public protocol KeyedEncodingContainerProtocol { associatedtype SuperEncoder: Encoder mutating func superEncoder() -> SuperEncoder ... } にできないのかがよくわかってないです。 API 全体で existential を排除できないものなのか・・・。ちょっと時間のあるときにちゃんと読んで理解して考えます。
2:13 AM
話はまったく変わるんですが、↓みたいなのほしくないですか? extension Array { public mutating func update(_ operation: (inout Element) throws -> ()) rethrows { for i in startIndex..<endIndex { try operation(&self[i]) } } } struct Foo { var value: Int } var array = [Foo(value: 2), Foo(value: 3), Foo(value: 5)] array.update { $0.value *= 2 } print(array) // [Foo(value: 4), Foo(value: 6), Foo(value: 10)] (edited)
Avatar
omochimetaru 4/30/2017 2:32 AM
array = array.enumerated().map { $0.0 + $0.1 } // 配列の要素の値に要素番号を足す
2:33 AM
インプレースなmapだと思うけどこういう場合に使えなさそう
2:35 AM
rubyだとmap! がありますね。(!は自己変更オーバーロードの慣習
Avatar
先のinoutなreduceの絡みで、mapよりupdateが欲しい場面が出てきそう
2:37 AM
返り値がvoidである必要があるから、必然的にupdateの方が取り回しやすい
Avatar
omochimetaru 4/30/2017 2:41 AM
そうなんだよなあ inout reduceがあるなら、これもあっていい、っていう議論がたくさん出てきそう
Avatar
あっても良いというか、メモリ効率考えると無いと困るってレベルだと思う
2:42 AM
filter, map, reduce (flatMapも?)こいつらは、自己変更のメソッドも欲しい
Avatar
omochimetaru 4/30/2017 2:43 AM
flatMapは無理じゃ無い?型的に
Avatar
Array<T>に対して返り値がArray<T>かOptional<T>なら大丈夫じゃない?あまり考えてないけど
Avatar
omochimetaru 4/30/2017 2:44 AM
あ、ごめん、そうだった
Avatar
mapとflatMapは基本的にはTからUだけど、自己変更はTからTしか有り得ない
Avatar
omochimetaru 4/30/2017 2:44 AM
flattenと間違えた
Avatar
reduceが、返り値持ってるからVoidで自己変更するわけじゃなく、返り値のUに対して自己変更を強制するから
2:46 AM
こいつだけオーバーロードでも違和感がないように見える、filter, map, flatMapはVoidにしないと成り立たない、オーバーロードは地獄を見そう。名前変更が妥当だけど
2:46 AM
全部updateに詰めればいいかな?
2:47 AM
mapはinout Tで大丈夫だけどflatMapとfilterはまた違うな…
Avatar
@tarunon そのあたりちゃんと整理しようとすると、例の filterfiltered みたいな話になると思うんですよね。ただ、 updatemap に相当するんですが、 map は戻り値の要素の型を変更できるのに対して update はできないんで、 map / mapped は違和感がありますね。 update / updated の方がいいけど、 mapupdated は弊害の方が大きそうだから、 updatemap かなぁと。
Avatar
norio_nomura 5/1/2017 3:52 PM
5月1日時点のmasterからtoolchainをビルドして使ってみたら、想像以上に変更点が多くてちょっと怯んでる…
Avatar
norio_nomura 5/2/2017 1:30 AM
ビルドしたtoolchainのインストーラ欲しい人いるかな?
Avatar
swift-evolutionの"[swift-evolution] [Pitch] Revamp Optional and Throws" スレッドでのJohn McCallのコメント。コアチーム(の中でもエラーハンドリング分野で一番影響力がありそうなJohn)の考えが知れておもしろい。 We've definitely considered including a Result type, but our sense was that in an ideal world almost no code would be using it. It's hard to imagine an ordinary API that ought to be returning a Result rather than throwing, and once you've defined that away, the major remaining use case is just to shift computation around, like with a completion handler. That explicit computation-shifting pattern is something we're hoping to largely define away with something like C#'s async/await, which would leave Result as mostly just an implementation detail of such APIs. We didn't want to spend a great deal of time designing a type that would end up being so marginal, especially if the changing role would lead us into different directions on the design itself. We also didn't want to design a type that would become an obstacle to potential future language changes like, say, typed throws. The downside, of course, is that as long as we lack that async/await design, computation-shifting isn't real great.
1:58 AM
前も書いたけど、↓みたいな感じで async / await 導入されてほしい。 https://gist.github.com/koher/df007741788cb197d65b6babe2acf480
Avatar
norio_nomura 5/2/2017 2:01 AM
async / await って GCD の上に構築されるイメージ?
Avatar
GCD とは直交なイメージです。 GCD は非同期処理を実行するためのもので、 async/await は非同期処理をハンドリングするためのものみたいな?
2:03 AM
僕がイメージしているのは、 throwsResult<T> は相互変換できるので、同じようにして asyncPromise<T> を変換できるというものです。
2:03 AM
なので
2:04 AM
throws : async try : await Result : Promise がすべて同じ関係になるだろうと。
2:04 AM
そう考えると、 rethrows と同じように reasync という概念が必要になるんじゃないかと思ってます。
2:05 AM
let r = await [2, 3, 5].map { (x: Int) async -> Int in ... }
2:06 AM
throws なクロージャが渡された maptry しなきゃいけないように、 async なクロージャが渡された map は↑のように await しなきゃいけないようにしたいと。 (edited)
2:07 AM
reasync がないと、 mapasync なクロージャを渡せなくなってしまいます。
Avatar
asyncにおいて、catch相当のものってあるんですか?
Avatar
catch とはエラーハンドリングの意味ですか?それとも、非同期処理において、エラー処理における catch に対応するものという意味ですか?
Avatar
後者です
2:17 AM
try-catchに対してasync-???
2:17 AM
いや、await-???か
Avatar
↑のGistでは do - defer (このキーワードが適切かは微妙です)で await 前のスレッドに戻ってノンブロッキングな処理を表すのがいいんじゃないかと思ってます。
2:19 AM
// `do` / `defer` for `await` outside `async` functions func onClick() { do { let selectedIndex = await actionSheet([...]) ... } defer // Non-blocking }
Avatar
この場合、deferに渡される値はどういうものが来るんですか?
Avatar
この場合は値は渡されません。
Avatar
あと、deferの中でreturnが可能、つまりyield的な動き?
Avatar
repeat - whilewhile ブロックがないように、 do - defer には defer ブロックがない想定です。
Avatar
norio_nomura 5/2/2017 2:22 AM
C#の await だと、変数間の依存関係も考慮されているみたいだけど、それも含む? func foo(url: URL) async throws -> Foo { let data = await try download(url) let modified = await asyncConvert(data) return Foo(data: modified) }
Avatar
変数間の依存関係とはどういうものを指してますか?
Avatar
norio_nomura 5/2/2017 2:23 AM
http://qiita.com/acple@github/items/8f63aacb13de9954c5da から引用 async Task<string> AsyncMethod2(Uri uri) { using (var client = new HttpClient()) // <- 本当はHttpClientをusingで使っちゃダメ { var response = await client.GetAsync(uri); // <- 「GETせよ」のタスクを開始し、その完了を待機する var text = await response.Content.ReadAsStringAsync(); // 「レスポンスからその本文をstringとして読み出す」タスクを開始し、その完了を待機する return text; // 読み出したtextを返す } } // という「一つのタスク(Task<string>)」を表す。 (edited)
この記事は、
  • Task.Runを書けばとりあえず非同期で動くのはわかる
  • 時々なんかうまく動かなかったりするけどどうして動かないのかはよくわからない
  • よくわからないまま書いてよくわからないまま動いてるけどこれで大丈夫なのか...
2:24 AM
response が返ってくるのを待ってから response.Content.ReadAsStringAsync() を呼んでる?
Avatar
そうなります。
2:25 AM
tryawaitflatMap に対応するので
2:25 AM
(そして PromisethenflatMap と等価なので)
2:26 AM
await を 2 回書くということは then をチェーンして繋いでるのと同じです。
Avatar
tryもそうですよね、なので現状swift-doはResultに対してはHakellのdo構文と同じ
Avatar
はい、そうです。
2:28 AM
なので、 async / await で、 Promise に対する( Haskell の) do のように振る舞えるはずです。
2:29 AM
JS の Promise はエラーハンドリングまで含んじゃってて筋が悪いですが、 async / awaitthrows / try を組み合わせれば、純粋な非同期処理と純粋なエラー処理に分離できるはずです。
2:29 AM
async throws -> T な関数は、 Promise<Result<T>> を返すようなものですね。
Avatar
norio_nomura 5/2/2017 2:30 AM
C#はスレッドで実装されてるぽいけど、Swiftもスレッドでってことは無さそう。
2:31 AM
C#もキューみたいなのあった気もする。
Avatar
throws tryだと、catchすることで純粋なTを取り出すことが可能ですが
Avatar
あー、 Promise ベースで考えてたので、 await 以降がどこのスレッドで実行されるかは async な関数を実装する側次第と考えてましたが、 Promisereturn するのと同じ自由度でそれを書くにはどうするのかよく考えてませんでしたね。
Avatar
async awaitは、同等のことは可能ですか?つまり、yield的な待ち合わせの機能
2:32 AM
deferがそれかな
Avatar
throws tryだと、catchすることで純粋なTを取り出すことが可能ですが
catch じゃなくて try で、じゃないですか? catch の方は Error ですよね?
Avatar
えっと、tryを使ったfuncの返り値をTにするために、catchでError処理をするなりして型を純粋なTにする
Avatar
C#はスレッドで実装されてるぽいけど、Swiftもスレッドでってことは無さそう。 C#もキューみたいなのあった気もする。
これに関しては、大本の非同期化する関数自体が async になって、どれを使うかによって実現されることになると思います。
Avatar
func pureInt() -> Int { do { return try throwAble() } catch { //Error処理 return someValue } }
2:37 AM
こういうの
Avatar
ちがうか。↓みたいなのがあればいいのか。 func makeAsync<T>(_: ((T) -> ()) -> ()) async -> T
2:42 AM
func foo() async -> Int { return await makeAsync { emit in DispatchQueue.main.asyncAfter(deadline: .now + 5.0) { emit(42) } } } (edited)
2:44 AM
現実的にはエラーが起こることも考えて↓かな。 func makeAsync<T>(_: ((T) -> ()) throws -> ()) async rethrows -> T
2:45 AM
@tarunon それってエラーからの回復だから、非同期処理に対応させると同期化だと思うんですよね。
2:46 AM
なので、 do - defer 相当のものは同期化というのがあり得る気がしてるんですが、現実的にはノンブロッキング化する方が必要だろうなと。
2:46 AM
もし同期化であれば
2:47 AM
↓みたいな感じになるのかな・・・。 func pureInt() -> Int { do { return await asyncInt() } wait }
2:48 AM
こっちの方が理論上は catch によく対応してるような気はします。
2:49 AM
ノンブロッキングの方は、そういう関数があればいいだけな気もしますね・・・。 func doAsync(_: () async -> ()) みたいな。 (edited)
Avatar
ノンブロッキングはそもそも
2:50 AM
doの中でコールバック関数呼べば良いだけな気も
Avatar
↓ということですか? func onClick() { do { let selectedIndex = await actionSheet([...]) ... } }
2:52 AM
↑のケースは、( throws / try と同様に) onClickasync でないとコンパイルエラーがいいと思うんですよね。
Avatar
あいや
2:53 AM
話が噛み合ってない気がした、ちょっと考えます
Avatar
norio_nomura 5/2/2017 3:00 AM
async がついたメソッドは await 付きで呼ばなければならず、 await を呼ぶメソッドは do {} で同期化しない限り async としなければいけない。
3:01 AM
throwstry と同じ感じか。
Avatar
はい、そうです。
3:03 AM
理論上も throws -> T-> Result<T> と等価で、 tryflatMap と等価だから、 async -> T-> Promise<T> にも同じ関係が成り立つはずなんですよね。 ResultPromise も同じくモナドなので。
Avatar
norio_nomura 5/2/2017 3:07 AM
await で非同期実行が始まるのは、スコープ内で await 以降に await と無関係なコードが現れた時、って感じかな。
Avatar
// a(), b() は () async -> Int let a = await foo.a() let b = await bar.b() let sum = a + b ...// a(), b() は () -> Promise<Int> foo.a().flatMap { a in bar.b().flatmap { b in let sum = a + b ... } } のような感じですね。 (edited)
3:10 AM
なので、 a に代入するところから非同期に行われます。
Avatar
barはmapでは
3:11 AM
thenならオーバーロードですが
Avatar
let a = foo.a() let b = bar.b() let aa = await a let bb = await b let sum = aa + bb はあるんですかね
Avatar
@t.ae それはないね。
Avatar
async関数がawaitできるだけなら↑ができないきがする
Avatar
@tarunon sum を返しているわけでなく、後続処理があるイメージです。
3:13 AM
@t.ae それはできなくていいと思います。それができるということは、モナドなまま値を取り回すことになるので。それを避けているのが今の Swift の throws / try の構文かと。
Avatar
非同期処理を複数同時に走らせられないのはなんだかなーという気分が。 Promise使えって話ですが。
Avatar
確かに、簡単に複数同時に走らせる方法はほしいね。
3:16 AM
↓の場合、 ab は独立だから、並列して走ってもいいんだけど let a = await foo.a() let b = await bar.b() let sum = a + b (edited)
Avatar
bar.bではaを評価してないので、同時に走れても問題ない気がする
Avatar
あえて a が終わってから b が走ってほしい場合とかもあるから
Avatar
非同期だとこの手の合成問題が出てきますね、try-catchではなかった問題
Avatar
( Web API へのリクエストを同時にたくさん投げたくないとか)
3:18 AM
それを↑レベルの手軽な構文でコントロールするのは、モナドの範疇外になってしまって難しいなぁ。
Avatar
それは非同期を提供するクライアント側が気にすれば良いことで、async-awaitは愚直に並列で実行して良い気がします
Avatar
Promise モナドは「今は値はない、けどいずれ手に入る」を表して非同期的にイミュータブルに振る舞うだけだから、
3:19 AM
↑の例で a()b() が並列に実行されようが順番に実行されようが結果の変わらない世界の話なんだよなぁ。
3:20 AM
@tarunon その場合、 let bar = await foo.bar() let baz = await bar.baz() だと順番に走るんですよね?
3:20 AM
結構わかりづらくないですか?
Avatar
Promise.all的な関数を用意してもらえばそれで良い気がする。
Avatar
asyncで生成された値を評価するなら、待ち合わせが必要
3:22 AM
ですが、それ以外は極力並列に走って貰わないと、パフォーマンスが出なさそう
Avatar
値を使う瞬間に待ち合わせが発生するようにする?
Avatar
そんなイメージです
Avatar
分かりづらくはあるけれどそれで問題が起こるケースが思いつかないですねぇ。
Avatar
値を使わない場合に問題があるなら、それは非同期関数を提供する側が制御すれば良いはず
Avatar
たとえば、 Qaleidospace では Qiita の API を叩いてるんだけど、回数に制限があるから、順序関係のないコールの間でも間隔をコントロールしてて、そういうときにシーケンシャルにつながってほしいとかはある。けど、シンプルな構文でなら @tarunon さんの言うような、待ち合わせが必要な場合だけ待つ方式が良さそうですね。
Avatar
それって、APIClient作って、そっち側に一定時間に何回まで叩けるみたいな
3:27 AM
Queueを内蔵してasyncはそのまま提供すれば
3:28 AM
普通に隠蔽できると思うんですよね
Avatar
とすると、 // a(), b() は () async -> Int let a = await foo.a() let b = await bar.b() let sum = a + b ...// a(), b() は () -> Promise<Int> let a = foo.a() let b = bar.b() a.flatMap { a in b.flatMap { b in let sum = a + b ... } } 相当になりますね。
Avatar
あとはawaitって書いてあるところで待ってないという気持ち悪さが残るだけですね。
Avatar
let bar = await foo.bar() let baz = await bar.baz() ... の場合は foo.bar().flatMap { bar in bar.baz().flatMap { baz in ... } }
3:31 AM
あとはawaitって書いてあるところで待ってないという気持ち悪さ
たしかに
3:32 AM
まったく話は変わるんですが、 Array<Optional<T>> だけに extension 書くとかってかけます?
3:33 AM
extension Array where Element == Optional まで書いて、型パラメータが書けなくて固まった・・・
Avatar
norio_nomura 5/2/2017 3:41 AM
書けそう error: reference to generic type 'Optional' requires arguments in <...> extension Array where Element == Optional { ^ <Any> (edited)
Avatar
<Any>はともかく<Wrapped>はできるんですかね?
Avatar
typealias ArrayO<T> = Array<Optional<T>> extension ArrayO { func foo() -> Bool { return reduce(true) { $0 && ($1 != nil) } } } ↑は書けたけど、普通に Arrayextension になってる・・・
Avatar
norio_nomura 5/2/2017 3:47 AM
ああ OptionalWrapped は型指定出来無さそう
Avatar
@norio_nomura 型指定というか、型を指定せずにプレースホルダーのままにしたいです・・・
Avatar
norio_nomura 5/2/2017 3:48 AM
ジェネリックパラメータを指定できないから無理そうですね
Avatar
1> extension Array where Element == Optional<Any> { 2. func foo() -> Bool { 3. return reduce(true) { 4. $0 && ($1 != nil) 5. } 6. } 7. } 8> let a: [Int?] = [2, 3, 5] 9. print(a.foo()) error: repl.swift:9:7: error: '[Int?]' is not convertible to 'Array<Optional<Any>>' print(a.foo()) ^
3:51 AM
うーん、辛いですね・・・
Avatar
Optional<T>にextension生やしてそれを呼ぶとかでは? 処理によりますが
3:53 AM
reduceか。reduceはだめそうですね
Avatar
実際にやりたいのは Array ですらなくて、 Promise<Optional<T>> についてのみの extension を書きたいのです・・・
3:54 AM
せっかく where T == Foo が書けるようになって、演算子を一掃できると思ったんだけど・・・。
Avatar
norio_nomura 5/2/2017 3:55 AM
protocol HasWrappedType { associatedtype WrappedType } extension Optional: HasWrappedType { typealias WrappedType = Wrapped } extension Array where Element: HasWrappedType { func foo() -> Bool { return reduce(true) { $0 && ($1 != nil) } } } let a: [Int?] = [2, 3, 5] print(a.foo()) let b: [Int] = [2, 3, 5] //print(b.foo()) // error: type 'Int' does not conform to protocol 'HasWrappedType' (edited)
👍 1
Avatar
なるほど・・・
3:57 AM
ワークアラウンドの protocol を外部に露出しないといけないですが、仕方ないですね・・・
3:57 AM
ありがとうございます!
🙂 1
Avatar
norio_nomura 5/2/2017 4:08 AM
StringBidirectionalCollection に変わるので joined() の型も変わってしまう。 var str = [ "Hello, playground" ].joined() type(of: str) // 3.1: String.Type, 4.0: FlattenBidirectionalCollection<Array<String>>.Type
Avatar
このあたりの変換後の型を Array にするのか lazy な型にするのかって難しいですよねぇ・・・
Avatar
norio_nomura 5/2/2017 4:10 AM
extension Array where Element == String { public func joined(separator: String = default) -> String } より extension Array where Element : BidirectionalCollection { public func joined() -> FlattenBidirectionalCollection<Array<Element>> } が優先されてる。
4:11 AM
優先順位の処理、これであってるのかな。
Avatar
ええっ、前者の方が specific に見えるのに、そんなことになるんですか?
Avatar
norio_nomura 5/2/2017 4:11 AM
昨日ビルドしたtoolchainでこうなります。
Avatar
なるほど・・・
Avatar
norio_nomura 5/2/2017 4:14 AM
SE-0166 と SE-0167 を試そうかと。
Avatar
試したいですね。
Avatar
norio_nomura 5/2/2017 4:17 AM
署名したインストーラ作ったけど、使ってみますか?
Avatar
Now that String conforms to the BidirectionalCollection protocol, in the expression let x = [""].joined() the best matching overload for joined is no longer the one returning String. Fixes: rdar://...
👍 1
Avatar
norio_nomura 5/2/2017 4:19 AM
出来立てだw
4:19 AM
4.0 SNAPSHOT そろそろなのかなあ
Avatar
署名したインストーラ作ったけど、使ってみますか?
Swift のインストーラーですか?
Avatar
norio_nomura 5/2/2017 4:19 AM
そそ
4:20 AM
Discordのファイル共有は50MBまでか。
Avatar
ありがとうございます。
Avatar
norio_nomura 5/2/2017 4:32 AM
warning: 'flatMap' is deprecated: This call uses implicit promotion to optional. Please use map instead. とか言われてビビる。
Avatar
ええっ
Avatar
ArrayのOptional flatMapですか?
Avatar
norio_nomura 5/2/2017 4:35 AM
ぽいです
4:37 AM
あいや、違うのかな。
4:39 AM
間違った使い方を指摘してくれてるぽい。
Avatar
おお!
4:39 AM
素晴らしい
Avatar
let a = [1,2,3].flatMap { $0 + 1 } こういうやつ。closure の返値が いったん Optional になるから、効率が わるい 悪かった。 (edited)
Avatar
norio_nomura 5/2/2017 4:42 AM
Due to implicit promotion to optional it is possible to call flatMap with a closure, that does not return an optional. This way the code works, but is unnecessary inefficient. Such uses of flatMa...
Avatar
norio_nomura 5/2/2017 4:51 AM
String を + で連結するとビルドが遅くなる問題って、まだ直ってないですよね。
Avatar
norio_nomura 5/2/2017 6:59 AM
Linux用のテストを返すallTests の定義で throws ではないメソッドを返す時にエラーが出る様になった。 extension ResolverTests { static var allTests: [(String, (ResolverTests) -> () throws -> Void)] { return [ ("testBasic", testBasic), ("testDefault", testDefault) ] // .map { entry in (entry.0, { entry.1($0) }) } // workaround } } … error: cannot convert value of type '(ResolverTests) -> () -> ()' to expected element type '(ResolverTests) -> () throws -> Void' ("testBasic", testBasic), ^~~~~~~~~ (edited)
Avatar
norio_nomura 5/2/2017 8:51 AM
SE-0166 イマイチかも…
Avatar
マジすか。どこがだめですか?
Avatar
お、SE-0166は気になる
🙂 1
Avatar
norio_nomura 5/2/2017 9:04 AM
自前の Encoder を作ろうとしての感想です。 SE-0167で実装された JSONEncoderPlistEncoder をそのまま使うぶんには良いのかもしれません。
Avatar
自前実装のどのあたりでイマイチなことになりましたか? SE-0166 は自前 Encoder / Decoder 実装がうまくいかないと意味がないと思うんですよね。 JSON とかだけでなく、汎用的な仕組みとして作られているのがおもしろいところだと思うので。 (edited)
Avatar
norio_nomura 5/2/2017 9:07 AM
libYAML のラッパーである https://github.com/jpsim/Yams/Encoder にするにはどうしたら良いのか?を前提にコードを眺めていました。
Yams - A Sweet and Swifty YAML parser.
Avatar
なるほど。 YAML だと JSON と同じだからできそうな気がしますが、 JSONEncoderJSONSerialization に渡すための NSMutableDictionary を生成すればいいけど、 Yams 用のインプットを Encoder の仕組みで組み立てるのが難しいとかですか?
Avatar
norio_nomura 5/2/2017 9:17 AM
Node っていうのが Yams での値/コンテナなのですが、これを enumstruct のペイロードで作ってしまっているので、逐次シリアライズした NodeKeyedEncodingContainerProtocol とかの内部情報として持てなくなってしまいました。
9:20 AM
JSONEncoderPlistEncoder はどちらも内部形式は NSMutableArrayNSMutableDictionary で、入れ物を親のコンテナに入れてから参照してる。
Avatar
Node を逐次シリアライズするのではなく、 _JSONEncoderNSMutableDictionary を組み立てるのと同じように、コンテナ経由で Node を組み立てて、最後にシリアライズではうまくいきませんか?
Avatar
norio_nomura 5/2/2017 9:26 AM
うまくいくとは思いますが [AnyHashable: Any] を得るために、PropertyListEncoder とほぼ同じコードを再実装しないといけない感じです。
9:26 AM
PropertyListEncoderData ではなく [AnyHashable: Any] を吐き出す仕組みがあると、幸せになれそう。 (edited)
Avatar
たしかに Encodable で表現できるデータ構造って似たようなものだから、 Dictionary 化するヘルパー Encoder みたいなのがあればその後が楽そうな気もしますね。ちょっとまだ自分で実装してないのでイメージがちゃんとできてないかもですが。 (edited)
9:32 AM
もちろん、 Dictionary を経由することでパフォーマンスを損ねるケースもあるので、 Encoder が提供しているような直接組み立てていくための仕組みは必須ですが。
Avatar
norio_nomura 5/2/2017 9:34 AM
まあでも、参照型の Node を作ればそれなりにいけそうな気もしてきました。
Avatar
norio_nomura 5/2/2017 10:32 AM
ちょっと変な方向から入ってしまったけど、SE-0166普通に使うぶんには簡単で良い感じ。
😋 2
Avatar
昨日の async / await の話、 Swift 5 についての議論が始まったら swift-evolution に投稿してみようかと思うんですが、↓みたいな感じでどう思います?わかりづらいところとか変なところとかあれば。 https://gist.github.com/koher/3e04b4f1b8adbbf0379d38c0ad83a3ea ノンブロッキング化する方法についても書いた方が良さそう。
Avatar
asyncとthrowsを組み合わせた時に何が起こるのかが解りにくい気がします
3:17 AM
1. 入れ子関係は固定なのか (必ずasyncが外側? 2. Errorの扱いがどうなるのか (↑の通りなら () async -> Error になっている? 3. waitとcatchの併用が可能なのか、併用したときのErrorの扱いについて
Avatar
@tarunon ありがとうございます。修正してみます。
11:28 PM
2 はどういうことですか?
Avatar
waitでなければ、catchのタイミングも非同期化しますよね?(あっている?
Avatar
async throws な関数をコールして catch だけするとどうなるのかということですか? (edited)
Avatar
はい
Avatar
そうですね。その場合は catch が非同期化されますね。
11:42 PM
Details みたいな形でそういう説明を足した方が良さそうですね。ありがとうございます。
Avatar
@tarunon#5049 「waitとcatchの併用」については downloadFooSync がそうなってました。また、 nonblock について書き足し、その中で catch しかしない例を追加しました。
3:08 AM
asyncthrows はどの順に書いても async が外側扱いがいいんじゃないかと思っていますが、そのあたりの詳細は ML で議論されればいいのかなと思います。あまり詳細に踏み込むと読むのが大変なのでとりあえず提案を投げるにはこれくらいのボリュームがいいのかなぁと。 (edited)
Avatar
なるほど、それもそうですね。
Avatar
モナドの中でenumを扱うときに、flatMapでassociatedvalueを取り出したくなることありませんか?上手い方法無いのかな
5:12 AM
enum MyEnum { case foo(Int) case bar(String) } func someAction(elements: [MyEnum]) { elements.flatMap { $0.foo } // ← [Int]が欲しい }
5:13 AM
foo: Int?とか生やして誤魔化してるけど流石に増えてくると辛くなってきた
Avatar
うーん、↓とかしか思いつかないですねー。 elements.map { guard case let .foo(foo) = $0 else { fatalError() } return foo }
Avatar
fatalは流石に困るw
6:01 AM
computed var foo: Int? でflatMapが妥当ですかねぇ、しょうがないか
Avatar
ああ、そうか。↓ですね。 elements.flatMap { guard case let .foo(foo) = $0 else { [] } return [foo] } (edited)
Avatar
まあ事実上そうですね
6:04 AM
多分ほぼ全てのモナドはOptional互換ではあるはずなので
6:04 AM
enum側にOptionalのアクセサ用意するのが妥当っぽい、となると言語機能でサポートして欲しいなーとなってくる
Avatar
↑って汎用Eitherがほしいって話な気がします。
Avatar
汎用Eitherというかですね
6:05 AM
Viewとロジックをつなぐのに、大量にイベントエミッター書くのがだるくて
6:05 AM
enumで流してしまえ~と思って public enum Output { case dataSources([Model]) case loading(Bool) } こういうのを書くと
6:06 AM
使う側でswitch書くのがしんどくなってしまった
6:06 AM
caseは大量に増えることもあり得るので、汎用Eitherが、n個のパターンで使えればOKっぽい
Avatar
うーん、n個のケースのそれぞれをflatMapで残したいとすると、やっぱり var foo: Foo? とかをそれぞれ作るしかない気がしますねー。
6:41 AM
case .foo(return) ?? nil みたいな書き方ができればいいんですが。パターンマッチング部分を抽象化できれば関数にできるんですけどね。
Avatar
パターンマッチの抽象化ほしいですね
Avatar
What do you mean Swift doesn’t have mixed-type arithmetic? let (x : Int, y : Double) = (3, 1) let result = Int + Double // 4
12:18 AM
これ動くの謎ですねw
Avatar
えぇ…
Avatar
ん?これって単にラベル付きタプルとして解釈されてるんじゃないですか?
12:26 AM
ラベル xy を持った IntDouble という定数にそれぞれ 12 が代入されてて
12:26 AM
(それらの型は Int です)
12:26 AM
それが足されてるだけに見えます。
12:28 AM
↓のような意味だと思いますが、明示的に型を書くとエラーになりますね・・・。 let (x: Int, y: Double): (Int, Int) = (1, 2) let s = Int + Double
12:29 AM
1> let (x: Int, y: Double) = (1, 2) 2. let s = Int + Double Int: Int = 1 Double: Int = 2 s: Int = 3
12:29 AM
1> let (x: Int, y: Double): (Int, Int) = (1, 2) 2. let s = Int + Double error: repl.swift:1:6: error: tuple pattern element label 'x' must be '_' let (x: Int, y: Double): (Int, Int) = (1, 2) ^
Avatar
let (x:Int,y:Double)←これが型宣言ではないのがポイントっぽい
12:39 AM
でも定数名を型名と同じ宣言したらそれは弾いて欲しいですね
Avatar
うーん、 let (x, y): (Int, Double) = (1, 2) が正しいんでしょうが、ラベル付きタプルを宣言して代入という構文も、何のためにラベルがあるのか意味不明なので、 let (x: Int, y: Double) = (1, 2) とできてもいい気がしますね。
Avatar
そもそもこれができるのが罠ってことですねー どうしてもやりたい場合(って何だ)はバッククオートつければいいだけだし、弾いてほしいですね
Avatar
それはそれとして、ラベル付きならxとyはどこへ…?というのがあって、混乱を生んでいて良くない
1:24 AM
つまり、let (x:y,z:w) =(1,1)でも通るって事ですよね
1:26 AM
1:26 AM
フーム
Avatar
1> let (a: b, c: d) = (1, 2) b: Int = 1 d: Int = 2
1:29 AM
挙動が違う??
Avatar
いや、同じですね
1:30 AM
aとcは存在しない
Avatar
ああ
1:30 AM
代入の後でラベルを使おうとしてエラーですね。 (edited)
Avatar
sandboxもxとzが無なので
Avatar
ラベルはあくまでタプルに紐付いているはずなのでそれはいいとして、ラベルが書けるの自体がミスリーディングですよねぇ。
Avatar
let Int=1 let Double=2 _=(x: Int, y: Double) 実際にはこれと等価
1:53 AM
xとyへの参照は無、IntとDoubleが残る。 tupleの型宣言 typealias Foo=(x: Int, y: Double)と混ざって混乱する
Avatar
あははは
Avatar
でもlintで弾くしか無さそうだ
1:56 AM
例えばネストした型としてローカルなURLを作りたいとか、それが必ずしも型であるとは限らない(メタな挙動をする変数かも知れない)なので、
1:58 AM
とは言えwarningぐらいは欲しいかなw 型名を変数で上書きしてる、と
Avatar
型の上書きよりも、問題は let (foo: x, bar: y) = ... のラベルを書けることじゃないですか?コンパイルエラーでいい気が。
Avatar
それはそんな気がします
2:01 AM
いやーー
2:02 AM
そうか、そうなるか
2:03 AM
let (x,y)=(1,2)これタプルじゃなくて、xとyに1と2を代入、ですね
2:03 AM
じゃあラベル付きは完全にダメだ
👍 1
Avatar
む、タプルじゃないんですね
2:16 AM
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID60 >If the right side of the assignment is a tuple with multiple values, its elements can be decomposed into multiple constants or variables at once: let (x, y) = (1, 2) // x is equal to 1, and y is equal to 2
2:16 AM
本当だ、左辺は、 "multiple constants or variables" ではあるけどタプルじゃないのかー
Avatar
右辺はタプルで、それを平たく展開するための代入。なのでラベルが使えるのはおかしい、と言うことですね。
👍 1
Avatar
タプルとラベル関連でもう1ネタ
2:54 AM
これ、なんで制限されてるのか合理的な理由あるんでしょうかね
2:57 AM
と思ったけど自己解決 そもそもrequest parametesには括弧が必要だからですね
Avatar
tupleとargumentの境界は4で厳密になるんでしたっけ?今は曖昧ですよね
Avatar
そこらへん関わってそうなproposalsは、 3でimplemented: swift-evolution/0029-remove-implicit-tuple-splat.md at master · apple/swift-evolution https://github.com/apple/swift-evolution/blob/master/proposals/0029-remove-implicit-tuple-splat.md swift-evolution/0066-standardize-function-type-syntax.md at master · apple/swift-evolution https://github.com/apple/swift-evolution/blob/master/proposals/0066-standardize-function-type-syntax.md swift-evolution/0111-remove-arg-label-type-significance.md at master · apple/swift-evolution https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md 4での総仕上げがこれ、ですかねー swift-evolution/0110-distingish-single-tuple-arg.md at master · apple/swift-evolution 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.
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
norio_nomura 5/6/2017 4:40 AM
ようやく SE-0166 準拠の YAMLEncoder が最低限動く様になった (edited)
㊗ 4
Avatar
@norio_nomura おお、素晴らしいですね!
🙂 1
2:37 AM
例の async / await について Ray さんが添削してくれたんですが、めっちゃ勉強になりますね。これがネイティブの英語力かぁぁ・・・。原文がほとんど残ってないw https://gist.github.com/rayfix/b5429a061a0fe34fa9326fe358dfdbe7/revisions
GitHub is where people build software. More than 21 million people use GitHub to discover, fork, and contribute to over 58 million projects.
Avatar
表現自体が違いますねw (edited)
😅 1
Avatar
norio_nomura 5/7/2017 1:00 PM
SE-0166 のEncoder & Decoderサポートのコードはこんな感じになりました。 https://github.com/jpsim/Yams/pull/43/commits/68c34b1ec8912688cfb1b0d23049e31ab9daf507 (edited)
Support SE-0166 Swift Archival & Serialization Fixes #38 This uses local built toolchain https://github.com/norio-nomura/swift-dev/releases/tag/20170501a TODOs for merging: Add text encoding dete...
😀 1
Avatar
norio_nomura 5/7/2017 2:02 PM
^SE-0166 対応を一通り実装してみての感想は、イマイチな部分もあるけど Mirror とかでシリアライズを作るよりはずっとマシ、ってところかな。
Avatar
この前ここで話してた SE-0171 の reduce について書きました。 http://qiita.com/koher/items/17636e95e18e529e5b9b
これまでの reduce は次のようなシグネチャでした。 ```swift func reduce( initial: T, combine: (T, Element) throws -> T) rethrows -...
👍 3
Avatar
norio_nomura 5/8/2017 3:50 AM
パフォーマンス云々を言うなら、辞書を init(minimumCapacity:) で作るとかした方が良いと思いました。
Avatar
コメントありがとうございます。キャパシティを確保しても計算量のオーダーレベルでは同じですし、 Before / After および for ループを使った場合との比較なのでキャパシティの話を混ぜるとわかりづらいかなぁと。
Avatar
norio_nomura 5/8/2017 4:04 AM
CoWだと辞書の元のキャパシティは維持されない様に見えるので、inoutだと再割り当てが確実に発生しないのはメリットに思えます。
4:07 AM
CoWで元のキャパシティが維持されない様に見えるのは、この辺り https://github.com/apple/swift/blob/3f68f2876ae6f859f777df638487544ddc62111d/stdlib/public/core/HashedCollections.swift.gyb#L4695
swift - The Swift Programming Language
Avatar
omochimetaru 5/8/2017 4:21 AM
COWでキャパシティが維持されるってどういういみですか?COWによってバッファのコピーが省略されて参照コピーになった際は、ストレージは共有されるけど、キャパシティ自体はストレージ自体に属するパラメータですよね
4:21 AM
実体のバッファコピーが起きた時に、新しく複製されたバッファにおいては、キャパシティが(例えコピー元が余裕のあるサイズになっていたとしても)それを引き継がずにリセットされる、という事?
4:22 AM
だとすると、Copy On Writeはあまり関係なくて、単純に、Dictinaryが実体コピーされたときのコストの話でしょうか
Avatar
norio_nomura 5/8/2017 4:43 AM
reduce へ渡す空の辞書を、生成されるであろう要素数を元に容量確保しておいても、最初のCoW発生時に辞書内の書き込み済み要素数を元に新しい辞書の容量が再計算されている様に見えます。 (edited)
4:48 AM
まあ、コピーされた時のコスト増だとも言えるかもしれませんが、コピーされないことによるメリットは最大限に享受したいなと。 (edited)
Avatar
omochimetaru 5/8/2017 4:51 AM
なるほど。 > メリットは最大限に享受したい
Avatar
仮に CoW でキャパシティが引き継がれるとすると、ループで毎回フルサイズ(最終的なサイズ)のバッファが確保されることになるので、かえって遅くなるんじゃないでしょうか。 inout のおかげで初期値をキャパシティ指定して渡すことの意味があるというのはその通りだと思うので、その点追記しておきます。
Avatar
↓連休中にレビュー入りしてた John McCall による Proposal 。 "This proposal is a core part of the Ownership feature, which was described in the ownership manifesto." らしい。 @omochimetaru が興味ありそう。 https://github.com/apple/swift-evolution/blob/master/proposals/0176-enforce-exclusive-access-to-memory.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 5/8/2017 6:28 AM
ちょうど読んでる
Avatar
@norio_nomura minimulCapacity の件、追記しました! http://qiita.com/koher/items/17636e95e18e529e5b9b/revisions/1?type=source (edited)
「Swift 4の新しいreduceが素晴らしいので紹介する」の編集履歴です。
🙂 2
Avatar
omochimetaru 5/8/2017 8:10 AM
struct Cat { var age: Int = 3 var po: Int { mutating get { age = 9 return age } nonmutating set { print(newValue) } } } こんな意味不明な事できた
Avatar
nonmutating 、 Swift が登場してすぐのときに Array の CoW がおかしくて、その関係で調査してたときに一度だけ使ったことある。
Avatar
omochimetaru 5/8/2017 8:12 AM
いま初めて書いたw
👍 1
Avatar
(2014.9.3に追記) 本投稿に書かれているのはbeta 2までの古いSwiftについての情報ですのでご注意下さい 。beta 3以降では、Arrayはletのときに要素が変更できなくなり、[すばらしく生まれかわり...
👀 1
Avatar
@moaible おお、よく発見できましたね!自分の古い投稿は見るのも恥ずかしいですねw
Avatar
norio_nomura 5/8/2017 9:25 AM
2週間以上DEVELOPMENT-SNAPSHOTが出てないけど、近日中に出そう。 https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20170501/004540.html
9:25 AM
Swift 4.0の変更がたくさん入ってるので楽しみ。
🙂 1
Avatar
↓これやっといて、 map[Element] を返すとか一貫性なくないですか?そして、 map についても Mapped を作ろうとしたら、 higher-kinded type がないといけないという・・・。 https://github.com/apple/swift-evolution/blob/master/proposals/0174-filter-range-replaceable.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
10:41 AM
最後に書かれてた。 It could be worthwhile to make a similar change to map, but this is beyond the capabilities of the current generics system because map does not preserve the element type
Avatar
mapは変更後の型Tがあるのに対してfilterは必要ないから差があるのか
11:51 AM
higher-kinded typeマジで欲しいですねぇ
🙂 1
Avatar
omochimetaru 5/9/2017 1:52 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
1:52 AM
番号が楽しいことになってる
Avatar
omochimetaru 5/9/2017 1:59 AM
毎回あったのか。初めて見ました。
Avatar
norio_nomura 5/9/2017 2:33 AM
SE-0176は以前rintaroさんが言ってた -enforce-exclusivity=checked のやつか。
Avatar
enumのassocvalueをeither的に、is-a関係を作りたい欲が高まってきた
2:47 AM
protocolとgenerics駆使すれば、現状でも似たことは出来るかしら🤔
Avatar
omochimetaru 5/9/2017 2:47 AM
enumとcaseじゃなくてcaseにぶら下がってるassoc valueと?
Avatar
そう
Avatar
omochimetaru 5/9/2017 2:48 AM
T is Optional<T>.Some と同じ事をユーザ定義したいってこと?
2:48 AM
たるのんそれ嫌いじゃなかったっけ
Avatar
そうそうそう
2:48 AM
まあそうだねw
Avatar
omochimetaru 5/9/2017 2:48 AM
闇に堕ちたんですか
Avatar
えっとですねー
2:48 AM
原初の欲求としては、assoctypeに複数値を持たせたいんですよ
Avatar
omochimetaru 5/9/2017 2:49 AM
昨日話してた可変長ジェネリックか
Avatar
複数種類の型を定義すると、複数種類の実装のオーバーロードで実現される。
2:50 AM
これが出来るとですね、assoctypeで引数を束縛するような、2つの型の関係が
2:50 AM
1:1,1:多しか今は出来ないが
Avatar
omochimetaru 5/9/2017 2:50 AM
Tuple2にある機能はTuple3にも全て欲しい、みたいな?
Avatar
多:多が可能になる
2:50 AM
いや、タプルとは違うな
2:51 AM
Viewから実装を引っぺがして、それをGenericsに作ることで
2:51 AM
NibとGenerics型の共存が出来ないかなと考えてるところから派生してる
2:52 AM
これ自体は上手く行きそうなんだけど、Viewと実装の繋ぎ込みがfuncになっちゃって、型を書くのが怠いから、assoctypeで縛ろうとしたが…
2:52 AM
という感じ、Viewと実装をassoctypeに持つ第三の型を作ればいい気もするけど、登場人物はなるべく増やしたくない
Avatar
omochimetaru 5/9/2017 2:54 AM
よくわからないけど、型Aと型Xの組み合わせのときの処理を静的に定義したい、そのペア自体を型付けしたい?
Avatar
extension View: HasImpl { typealias Impl=Int } ↑これだと、Intしか実装がない。なので、IntかStringを使おうとすると↓ extension View: HasImpl { typealias Impl=Int|String } ↑こういうのが欲しくなる
2:55 AM
そうそう
Avatar
omochimetaru 5/9/2017 2:55 AM
(A/B/C) x (X/Y/Z) のような合成がしたいと
Avatar
そう!
Avatar
omochimetaru 5/9/2017 2:55 AM
で、 (*) x (X) とか (A) x (X) とか (A/B) x (*) の場合における実装を定義したい? (edited)
Avatar
えーっと、そこの掛け算全部書くのは吝かではない (edited)
Avatar
omochimetaru 5/9/2017 2:56 AM
なるほど
2:56 AM
あー、 A / B / C とかは個別の データモデル型とか 個別のViewだから enum にならんのか
Avatar
型を書くのが怠いから、推論機からポンッと出したいよね、という
2:57 AM
ABCは共通のデータモデル使うぞ
2:57 AM
データモデルの側が色々あり得る
Avatar
omochimetaru 5/9/2017 2:57 AM
型は違うんだよね?
Avatar
そこは別に同じでも良い
2:58 AM
えっとね
Avatar
omochimetaru 5/9/2017 2:58 AM
ふむ。
Avatar
これが出来ると、TableViewControllerを一個作っておくと、ユーザ一覧実装と、ツイート一覧実装をぶち込めば
2:58 AM
それぞれの振る舞いが出来るようになる
2:59 AM
CollectionViewControlldrに、同様にbindingの実装を加えれば、こちらにもユーザ一覧やツイート一覧をぶち込むことが可能
2:59 AM
で、そうするとですね、
3:00 AM
実装側は、モデルの型を持っているが、TableViewControllerにモデルの型を含む実装が必要。繋ぎ込むための関数をGenericsベースで作ろうとすると、多対多のassoctype宣言が必要に
3:01 AM
enumで行けないかな?→union!!!
3:01 AM
ってなった次第
Avatar
omochimetaru 5/9/2017 3:05 AM
GenericTableViewController < M : GenericTableViewcontrollerModelProtocol > extension TweetModel : GenericTableViewcontrollerModelProtocol { func bindToGenericTableViewController ... } こういう感じじゃ駄目なの?
Avatar
View自体にGenericsを入れるのはダメ
3:06 AM
Nibは使いたい(ワガママ)
👍 1
Avatar
omochimetaru 5/9/2017 3:06 AM
そこでNibが出て来るの・・・
Avatar
オートレイアウト手書きはやってられない
3:07 AM
多分、どこかprotocolに落として考えれば、通る型が作れるはずだから模索してみるかな
Avatar
何回読んでも超わかりにくい、端的にいうと、associatedtypeでオーバーロードがやりたいって話ですね
7:11 AM
結局unionが欲しいのと一緒だった
7:11 AM
🙄
Avatar
omochimetaru 5/9/2017 7:15 AM
protocol P { associatedtype AT } struct SP<T> : P { typealias AT = T } extension P where AT == Int { func po() { print("AT == Int") } } extension P where AT == String { func po() { print("AT == String") } } let intsp = SP<Int>() intsp.po() let strsp = SP<String>() strsp.po()
7:15 AM
associatedtypeでオーバーロードがやりたい
だけだと、これでできているように見える?
Avatar
Generics無しだと出来ないよね
7:15 AM
つまり
7:16 AM
同一のspからIntとStringでオーバーロードされたfunctionやfieldにアクセス出来る必要がある
Avatar
omochimetaru 5/9/2017 7:16 AM
どっちになるかは何をもって決まるの? (edited)
Avatar
かつ、Pで束縛するときのATがIntとStringどちらでも使えないといけない
7:17 AM
外側の型で束縛される
Avatar
omochimetaru 5/9/2017 7:19 AM
同一のspって、そのspの式の型はPって事?associated typeがあるからそのような変数は作れない
Avatar
norio_nomura 5/9/2017 8:22 AM
こんな感じ? protocol P { associatedtype AT } protocol HasStringProtocol {} protocol HasIntProtocol {} extension P where AT: HasStringProtocol { func po() -> String { return "string" } } extension P where AT: HasIntProtocol { func po() -> Int { return 1 } } struct StringAndInt: HasStringProtocol, HasIntProtocol {} struct S: P { typealias AT = StringAndInt } let s = S() let string = s.po() as String // "string" let int = s.po() as Int // 1
Avatar
@norio_nomura お、近い。これでpoがPの型から見えていればいけそう
9:00 AM
でも多分それ以上は出来ないですね、今の機能で欲しいものは作れない気がしているのであきらめムードです。
Avatar
protocol P { associatedtype T func hoge(t: T) } class MyClass {} extension MyClass: P { typealias T = Int func hoge(t: Int) {} } extension MyClass: P { typealias T = String func hoge(t: String) {} } func foo<MyP: P>(_ arg: MyP) where MyP.P == String {} // <- ここにMyClassを func bar<MyP: P>(_ arg: MyP) where MyP.P == Int {} // <- どっちでも入れれるようにしたい
Avatar
norio_nomura 5/9/2017 9:30 AM
無理ぽ
Avatar
UnionTypeがあれば
9:30 AM
Int|Stringで宣言して多分思い通りのものができそう
Avatar
最近Int|CountabelRange<Int>みたいなのをやろうとして、 結局ContableRangeをprotocolに従わせつつ関数側で型チェックってのになってしまったので Unitonがあると嬉しいですね。
Avatar
norio_nomura 5/10/2017 1:08 AM
subscript が identifier になるらしい。 間違い https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20170508/004549.html init みたいにメソッドとして参照できる様になるのかな。 ならない (edited)
Avatar
びっくりしました。一瞬キーワードが変わるという意味かと思いました。
Avatar
ヘッダー見ないとSubScriptあるの知れないからこれは嬉しそう
Avatar
foo.subscript ができるようになるのはうれしいですね。
1:40 AM
昨日話されてた Union Type については、影響範囲が大きすぎてなかなか難しいですよね・・・。
1:41 AM
Intersection Type はいらないのか、 Union, Intersection とオーバーロードの関係をどうするか、
Avatar
導入だけなら非破壊的な気がしますが
Avatar
サブタイピングがめちゃくちゃ複雑化するし
1:42 AM
Union Type は以前 swift-evolution でも議論されてたけど、概ね否定的な感じでした。
1:43 AM
個人的にはほしいときはありますが、
1:44 AM
基本的には Union みたいな Non-nominal type は必要最小限に留めて使うべきで、
1:44 AM
正しい用法用量を求めるのが難しそう・・・。まあ、それを言い出したらタプルと struct もすでにあるんですが。
1:45 AM
あと、 Smart cast もないと Union Type は使い物にならない。
Avatar
omochimetaru 5/10/2017 1:47 AM
(昨日のたるのんの話結局いまいち目的がわからなかった
Avatar
Intersection はオーバーロードと等価だから、↓みたいな問題も起こる。 func foo() -> Int { ... } func foo() -> Double { ... } // 今 let f: () -> Int = foo // () -> Int の foo が代入される // Intersection があったら let f: (() -> Int)&(() -> Double) = foo let g = foo // ↑と同じ let h: () -> Int = foo // この場合 h の実体は何? () -> Int の foo ?それとも f や g と同じ? (edited)
1:50 AM
あと、 Typed Throws が長い間議論されてるけど、導入するならエラー型を一つに絞るのがいいという話になってるけど、 Union Type があると func foo() throws BarError|BazError -> Foo ができるので複数エラー投げられることになってしまって台無しに・・・。
Avatar
omochimetaru 5/10/2017 1:50 AM
オーバーロードはintersection typeをもつ一つの型とはみなさないのが良さそう fの代入文がエラー
Avatar
@omochimetaru そうかなぁ。 Intersection があるならそれがやりたい気がする。
Avatar
omochimetaru 5/10/2017 1:54 AM
(() -> Int) & (() -> String) って () -> (Int | String) と等価か?
Avatar
Nominal なジェネリック型の型パラによる Variance も導入されてないのに、 Non-nominal な型のサブタイピングが導入されるとかきつそう。
Avatar
omochimetaru 5/10/2017 1:54 AM
いや、ちがうなあ
Avatar
違うね。
Avatar
omochimetaru 5/10/2017 1:55 AM
どちらでもあるんだから () -> (Int & String) と等価か
Avatar
それも違う。
1:56 AM
(Int|String) -> ()((Int) -> ())&((String)->()) は同じに見えるけど (Int|String) -> (Int|String)((Int) -> Int)&((String) -> String) は違う。
Avatar
omochimetaru 5/10/2017 1:58 AM
(Int|String) -> (Int|String) と ((Int) -> Int)&((String) -> String) これはわかる、引数で入れた型が返り値で出てくるっていう依存性が消えてるから違う
Avatar
() -> Int&Stringlet f: () -> Int&String = ... let r: Int&String = f() ができるけど、 (() -> Int)&(() -> String) は↓のどっちかしかできない。 let f: (() -> Int)&(() -> String) = ... let r1: Int = f() let r2: String = f()
Avatar
omochimetaru 5/10/2017 1:59 AM
え、でも、 r1 と r2 を合成して r が作れますよ
Avatar
それは (() -> Int)&(() -> String) を 2 回コールしないとダメでしょ。
Avatar
omochimetaru 5/10/2017 2:01 AM
型としては外からみれば1回のコールに見せかけられるのでは
Avatar
↓とか変じゃない? let f: (() -> Int)&(() -> String) = ... let r: Int&String = f() // 2 回コールされる
2:02 AM
r が二つのインスタンスの合成というのも変
Avatar
omochimetaru 5/10/2017 2:02 AM
型それ自体は本当に入ってる実体の数とは関係ない気がする たとえば Int & Int & String は Int & String だから
2:02 AM
Unionが畳み込めるのと同じような話で
Avatar
Union にせよ Intersection にせよ、複数のインスタンスを一つにまとめて扱うわけじゃなくて
2:03 AM
あくまで一つのインスタンスの性質の話じゃない?
2:04 AM
Intersection がある言語を使い込んだことがないけど、複数のインスタンスを一つのインスタンスのように扱えるものなの?
Avatar
omochimetaru 5/10/2017 2:06 AM
(() -> Int)&(() -> String) この型は () -> Int なんだから、一回呼び出せばIntが返るけど、 それと同時に () -> String なんだから、一回呼び出せば Stringが返るはずで、 それは () -> (Int & String) って事じゃないのかな () -> (Int & String) なら 1回呼び出せばIntが返るとも言えるし 同時に1回呼び出せば Stringが返るとも言える
2:07 AM
1つの値の性質の事だと思っているから、どちらかを呼び出すとか2回呼び出すとかいう話が出てくるほうが変な感じがする
Avatar
いや、 (() -> Int)&(() -> String) はただのオーバーロード。
2:07 AM
戻り値オーバーロードだからわかりづらいだけで
2:08 AM
((Int) -> ())&((String) -> ()) だと考えてみたら自明じゃない?
2:08 AM
foo(42)foo("xyz") ができるだけ。
Avatar
omochimetaru 5/10/2017 2:08 AM
((Int) -> ())&((String) -> ()) == (Int | String) -> () だと思う
Avatar
((Int) -> Int)&((String) -> String) でもいいけど。
Avatar
omochimetaru 5/10/2017 2:09 AM
それは1つの関数型には畳み込めない
2:09 AM
僕が存在すると思ってる型変換規則は2つあって
Avatar
1つの関数型には畳み込めない
このことが & はオーバーロードを表すことを示してるのでは?
Avatar
omochimetaru 5/10/2017 2:10 AM
いや、それはオーバーロードの概念がインターセクションと違う事を示しているだけで
2:10 AM
一般的に拡大するのは違うと思う
2:11 AM
(A -> B) & (A -> C) == (A) -> (B & C) (A -> B) & ( C -> B) == (A | C) -> B の 2つだけが適用できる
2:12 AM
「オーバーロード == 関数型2つのインターセクション」っていう仮定が正しければkoherの意見は一貫してるけど
2:12 AM
その仮定がそもそも違って
2:12 AM
オーバーロードのほうが条件が厳しい合成の概念で
2:12 AM
それをインターセクションと考えるとおかしくなるんじゃないかと思ってる
2:12 AM
SwiftのTagged UnionがUnion Typeよりも厳しくて畳み込んだりできないのと同じように。
2:13 AM
IntersectionTypeがある言語を僕も使ったことはないけど。
Avatar
そもそも二つのインスタンスを一つにまとめた存在というのがあり得るのがおかしい気がする。
Avatar
omochimetaru 5/10/2017 2:20 AM
あーそれは、違うと思います
2:20 AM
型の話とインスタンスの実体のかずがうんたらというのは別で
Avatar
↓ができるってことでしょ? let a: Int&String = 42&"xyz"
Avatar
omochimetaru 5/10/2017 2:20 AM
はい
2:21 AM
でもそれはその aInt を要求するところや String を要求するところ 両方にかけてコンパイルできる
2:21 AM
というだけの話で
2:21 AM
たとえば
2:21 AM
struct IntAndString { var i: Int var s: String } (edited)
2:21 AM
これでも満たせる
2:22 AM
.i.s のメンバアクセスをコンパイラが自動注入すれば
2:22 AM
式としてはそれで成立させられる
Avatar
そもそも何故欲しかったのかの注釈、 protocol Receiver { associatedtype Arguments func foo(_ arguments: Arguments) } protocol Sender { associatedtype Returns func bar() -> Returns } この二つの型を合成して使うことを考える、 Receiver.Argnumentsと、Sender.Returnsが一致していれば合成可能、故に合成関数は次の定義 func combine<R: Reciever, S: Sender>(reciever: R, sender: S) where R.Argnuments==S.Returns
Avatar
omochimetaru 5/10/2017 2:22 AM
Cat is Animal 則を満たす時に暗黙の調整処理が挿入されるのと同じ話だと思います
2:23 AM
ちょっと離席
Avatar
Recieverの実装を持っていて、受け取れる型の幅を増やしたい、unionがあればそれを使えば済む。しかし無い場合、 Recieverの型をenumにしたとして、それはつまり、Senderの型も書き換えないと行けない。
Avatar
@omochimetaru Intersection はあくまで型の合成であって、インスタンスの合成は異なる概念だと思う。
Avatar
で、↑だけど、さっき朝ご飯食べてたら多分天命降りてきたんで無くても辛さ解消できるかも知れない。
Avatar
↓でも Overload のことしか書いてなくて、インスタンスの合成なんて話は出てきてないように見える。
This corresponds precisely to our intended behavior for overloading
http://cs.brown.edu/courses/cs173/2012/book/types.html#%28part._.Intersection_.Types%29
2:31 AM
Union や Intersection はあくまで型の話であって、インスタンスは常に一つで、そのインスタンスがどのように振るまうかという話だと思う。 (edited)
Avatar
the DeclName for subscripts is just the Identifier “subscript”
この話ですけど、今までは subscript が内部的に単なる identifier としてモデリングされていたおかげで、 TypeCheckerで obj.subscript で参照できてしまい、SILではそんなこと意図されてなかったのでクラッシュしていたのが、この修正により 'Foo' has no member 'subscript' としてエラー出せるようになるっていうだけの話なのです。 https://bugs.swift.org/browse/SR-2575
🙏 1
Avatar
おおお、ほんとだ・・・。衝突した。 struct Foo { subscript(i: Int) -> Int { return i } func `subscript`(_ i: Int) -> Int { return i + 1 } } 9> Foo().subscript(42) error: repl.swift:9:1: error: ambiguous use of 'subscript' Foo().subscript(42) ^ repl.swift:2:5: note: found this candidate subscript(i: Int) -> Int { ^ repl.swift:5:10: note: found this candidate func `subscript`(_ i: Int) -> Int { ^ 9> Foo().`subscript`(42) error: repl.swift:9:1: error: ambiguous use of 'subscript' Foo().`subscript`(42) ^ repl.swift:2:5: note: found this candidate subscript(i: Int) -> Int { ^ repl.swift:5:10: note: found this candidate func `subscript`(_ i: Int) -> Int { ^ 9> Foo()[42] error: repl.swift:9:1: error: ambiguous use of 'subscript' Foo()[42] ^ repl.swift:2:5: note: found this candidate subscript(i: Int) -> Int { ^ repl.swift:5:10: note: found this candidate func `subscript`(_ i: Int) -> Int { ^ (edited)
Avatar
class Foo { func `deinit`() {} } が出来なかったのが出来るようになったりするかもしれないけど、その程度。
Avatar
あれ?逆に foo.subscript は今でもできるのかと思ったけど・・・。 1> struct Foo { 2. subscript(i: Int) -> Int { 3. return i 4. } 5. } 6> Foo().subscript(42) Segmentation fault: 11
2:55 AM
1> struct Foo { 2. func `subscript`(_ i: Int) -> Int { 3. return i 4. } 5. } 6> Foo().subscript(42) $R0: Int = 42 7> Foo()[42] Segmentation fault: 11 (edited)
Avatar
この変更で `func subscript subscript がしっかり区別されるようになり、前者は foo.subscript 後者は foo[...]` でしか参照できなくなります。
Avatar
今 Segmentation fault なのも変じゃないですか?
Avatar
はい、それを修正するための変更です。
Avatar
あと、 foo.subscriptsubscript が参照できないと、今の Foo.init とかができるのと一貫性がないような気がします。
Avatar
思想的には subscript はプロパティであるっていうので現状になっている感じがします。
Avatar
なるほど・・・。 Generic だけできるようになって中途半端な状態になってしまいましたね💦引数はとれるし、 Generic にできるし・・・。
3:09 AM
throws もできるようしたらメソッド側に寄せられますが・・・。
Avatar
evolution 洗ったけど foo.subscript できるようにするという議論された形跡みつからず 😥
Avatar
なるほど。ありがとうございます。
Avatar
omochimetaru 5/10/2017 3:33 AM
@koher 僕もそう思っています。 > @omochimetaru Intersection はあくまで型の合成であって、インスタンスの合成は異なる概念だと思う。
Avatar
やりたいことも型合成メインでインスタンスの合成は考えてないですね
Avatar
omochimetaru 5/10/2017 3:35 AM
func combine<R: Reciever, S: Sender>(reciever: R, sender: S) where R.Argnuments==S.Returns
3:35 AM
これのなかみは
3:36 AM
func combine<R: Reciever, S: Sender>(reciever: R, sender: S) where R.Argnuments==S.Returns { receiver.foo(sender.bar()) }
3:36 AM
これであってる?
Avatar
そう
Avatar
omochimetaru 5/10/2017 3:36 AM
なるほどなるほど
Avatar
enumでEither作って、Sender側もEither対応したReturnsにするのが苦痛
3:37 AM
でも、EitherになったSenderを定義してオペレーターで変換して、型推論が頑張ってくれないかな?ってやったら、まあ上手く行ったw
Avatar
omochimetaru 5/10/2017 3:38 AM
あーー T -> Optional<T>.Some のユーザー定義がしたいって
3:38 AM
そういうことかw
3:39 AM
オペレーターじゃなくても
3:39 AM
func combine<R: Reciever, S: Sender>(reciever: R, sender: S) where R.Argnuments==S.Returns { receiver.foo(convertReceiverType(sender.bar())) }
Avatar
それは無理じゃない?
Avatar
omochimetaru 5/10/2017 3:39 AM
ようするにこういう形にして
3:40 AM
convertReceiverTypeが receiverの受け付けられる型のかずだけ
3:40 AM
オーバーロードをしておけばいいんじゃない?
Avatar
combine側をオーバーロードするのか
Avatar
omochimetaru 5/10/2017 3:40 AM
combine自体が複数ないとだめか?
3:40 AM
試してみる
Avatar
でもね、それ、combineを使ってる全ての関数がオーバーロード必要になって
3:40 AM
地獄だな
Avatar
omochimetaru 5/10/2017 3:41 AM
combineじゃなくてあいだにはさんでる convertReceiverTypeだけで
3:41 AM
いけないかなあ
Avatar
できない
3:41 AM
それを実現するにはunionいる、あるならそもやらなくて言い
Avatar
norio_nomura 5/10/2017 4:36 AM
evolution 洗ったけど foo.subscript できるようにするという議論された形跡みつからず 😥
@rintaro 間違った情報を正していただいて、ありがとうございます 🙏
Avatar
結局、ここらへんが落とし所っぽい。 enum Either2<A, B> { case a(A), b(B) } class MyReciever: Reciever { typealias Arguments = Either2<String, Int> } // このままだとStringを吐き出すSenderは使えない class MySender: Sender { typealias Returns = String } // Either変換を含めた魔改造type-erasureを作る class Sender2A<R1, R2> { typealias Returns = Either<R1, R2> init<S: Sender>(_ sender: S) where S.Returns == R1 } class Sender2B<R1, R2> { typealias Returns = Either<R1, R2> init<S: Sender>(_ sender: S) where S.Returns == R2 } // 変換オペレーターを差し込む prefix operator ~ prefix func ~<S: Sender, R>(_ sender: S) -> Sender2A<S.Returns, R> { return .init(sender) } prefix func ~<S: Sender, R>(_ sender: S) -> Sender2B<R, S.Returns> { return .init(sender) } combine(MyReciever(), ~MySender()) // OK!
Avatar
omochimetaru 5/10/2017 4:51 AM
あ、打ち合わせしてた
4:51 AM
connect(IntProvider(), IntOrStringConsumer()) { .lift($0) }
4:51 AM
↑これでどうでしょう
Avatar
やっぱそういうの付けなきゃいけない
4:51 AM
combine側にそれが必要だと、combineを利用するすべての関数で作らないといけない
4:52 AM
負の連鎖になるから、引数の時点で解決したほうが良いかなぁ
Avatar
omochimetaru 5/10/2017 4:53 AM
tarunonがやったほうほうでも ~ をつけるんだから同じじゃない?
4:54 AM
~ は短いけど何が起きてるかあとでわからなくなりそう
Avatar
いや、combineを利用して実装している関数に、機能を追加すること無く使えるのがポイント
4:54 AM
まあ~じゃなくて、.converted()でも良い
Avatar
omochimetaru 5/10/2017 4:54 AM
なるほど
4:54 AM
ようするにこれってモナドの.mapだよね
Avatar
そうそう
4:56 AM
最近Swiftの型でサブタイピング無くて発狂したらなんでもかんでも~で解決する癖がついてきた…
4:58 AM
明示的なサブタイピングの手法と考えれば、~で大体OKだな、という気がする。
5:00 AM
お、俺は間違ってない…間違ってないはずだ… https://github.com/tarunon/Hiyoko/blob/refactoring/viewmodel/Reactor/Sources/Either.swift#L626-L681
Hiyoko - https://www.hiyoko.co.jp, It's a sweets in Fukuoka. But this repo maybe become twitter app for iOS.
5:00 AM
改めて見ると笑うなこれ
Avatar
omochimetaru 5/10/2017 5:02 AM
関数を中にいれるのだと型が定まんないからだめなんだなあ
Avatar
それもそうね
Avatar
omochimetaru 5/10/2017 5:02 AM
オーバーロード探索の前に推論が終わらないといけないのか
5:03 AM
うまくいえないが
5:03 AM
プロトコルさしまくればなんとかなりそうだけどちらかって微妙な感じ
Avatar
全てをGenericsで定義していけば、多分うまくいくのだけど
5:04 AM
今回はViewControllerとViewはStoryboard/Nibを使うからGenericsダメって制限があるので
5:04 AM
そのジョーカーは使えない。
Avatar
omochimetaru 5/10/2017 5:05 AM
Genericsでも Int Or String が表明できないから無理じゃない?
Avatar
あーーー
5:05 AM
それも、そうだ
5:06 AM
この間の返り値のタプルで推論させたのは
5:06 AM
そもそも最初がサブタイピングあるやつだ
5:06 AM
今回は無い
5:06 AM
Avatar
omochimetaru 5/10/2017 5:06 AM
つまり、言語仕様上暗黙の互換性が無いけど、コンバータを通せば渡せるようなケースで、そのコンバータを書きたくないっていうのが
5:06 AM
一般化したやりたい事なんじゃないかな
Avatar
そうそう
5:07 AM
まあ暗黙的にそれを許すのはヤバなので
5:07 AM
オペレーターはかなり良い落とし所
Avatar
omochimetaru 5/10/2017 5:07 AM
で、たまたま今回のケースはその2者が union関係だったから、union typeがあったらよかった、ということで
5:07 AM
String と struct FilePath みたいな2者でも同じ課題があると思う
Avatar
あとコンバーターが、引数に入れてinitすれば済むレベルの単純さ
Avatar
norio_nomura 5/10/2017 5:57 AM
@tarunon TWITTER_CONSUMER_SECRET がコミットされてるけど大丈夫ですか? https://github.com/tarunon/Hiyoko/blame/cf0f137321ef26d20a2940dd8d76de598012d207/Hiyoko/AppDelegate.swift#L13
Hiyoko - https://www.hiyoko.co.jp, It's a sweets in Fukuoka. But this repo maybe become twitter app for iOS.
Avatar
うわーっ
5:57 AM
ありがとうございますw
Avatar
omochimetaru 5/10/2017 5:57 AM
おw
5:57 AM
ツイッタークライアント作ってたのか
Avatar
GW前に丼作ってて
Avatar
omochimetaru 5/10/2017 5:58 AM
mstdn - mastodonクライアントアプリ開発RTA
5:58 AM
RIPしてたw
Avatar
アレは投げたけど実験場は欲しいのでTwitterクライアントの形で継続してる
5:58 AM
w
5:59 AM
キーとシークレットRevokeしました。ありがとうございます! @norio_nomura
🙂 1
6:00 AM
最近まで気を付けてたけどついにやってしまった、適当な.gitignoreに書いたplistから読むようにしよう
Avatar
omochimetaru 5/10/2017 6:00 AM
.swiftでもいいんじゃね
Avatar
コンパイルエラーになってしまうのはヤの感じかなー
Avatar
omochimetaru 5/10/2017 6:00 AM
コンパイルエラーのほうがマシじゃん
Avatar
それもそうか
Avatar
omochimetaru 5/10/2017 6:00 AM
plist書き忘れて何故か動かないより
Avatar
丼はなんか
6:01 AM
コンシュマーキーとシークレット作り放題なんで
6:01 AM
適当にやっててそれを引き継いだのが災いした
Avatar
norio_nomura 5/10/2017 6:04 AM
plist の方が CI で楽できそう
Avatar
CIは多分、HiyokoKitしか見ないんで
6:08 AM
Hiyoko本体がコンパイルできないのは特に問題無さそう
Avatar
norio_nomura 5/10/2017 6:31 AM
2週間以上DEVELOPMENT-SNAPSHOTが出てないけど、近日中に出そう。
swift-DEVELOPMENT-SNAPSHOT-2017-05-09-a パッケージングのCIが完走しそう。 https://ci.swift.org/view/Packages/job/oss-swift-package-osx/3351/console
Avatar
norio_nomura 5/10/2017 7:01 AM
swift-DEVELOPMENT-SNAPSHOT-2017-05-09-a きた https://swift.org/download/#snapshots
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
omochimetaru 5/10/2017 7:03 AM
ここで落とせるxcodeって
7:03 AM
xcode-selectでmacの中でスイッチして使える感じですか?
7:03 AM
あ、でも ownership 試す時はビルド自体のフラグを変えないといけないのかな
Avatar
norio_nomura 5/10/2017 7:10 AM
Xcodeの中で切り替えられます。
Avatar
omochimetaru 5/10/2017 7:11 AM
!?
7:11 AM
Simulattors | Documentation しかなかった 2つ以上あると Toolchains が現れるのか
Avatar
norio_nomura 5/10/2017 7:12 AM
ビルド時のtoolchainを切り替える方法は色々あるのですが、 xcode-select では切り替えられなかったはず。 (edited)
Avatar
omochimetaru 5/10/2017 7:13 AM
ふむふむ
7:13 AM
切り替える仕組みがあるなら変に混ざったりしなそうだしダウンロードしてみよ
Avatar
norio_nomura 5/10/2017 7:13 AM
Xcodeの場合エディタサポートかがあるため、起動しているXcode.appインスタンス全体で切り替わります。
7:14 AM
xcodebuildxcrun-toolchain オプションがあったり、TOOLCHAINS環境変数を使ったり。
Avatar
omochimetaru 5/10/2017 7:16 AM
xcrun-sdk は割りとつかいます
Avatar
norio_nomura 5/10/2017 7:17 AM
$ pkgutil --pkgs|grep org.swift org.swift.3020170509a org.swift.31120170421a でインストールしてある swift.org からのスナップショットのIDを探せるので、それを TOOLCHAINS=org.swift.3020170509a swiftxcodebuild -toolchain org.swift.3020170509a … みたいにして使います。 (edited)
7:18 AM
$ xcrun -toolchain org.swift.3020170509a swift Welcome to Apple Swift version 4.0-dev (LLVM 6a9a7bf93b, Clang 288cf0b5d5, Swift 2e09c17818). Type :help for assistance. 1> (edited)
Avatar
omochimetaru 5/10/2017 7:21 AM
ほ〜〜〜〜
7:21 AM
ありがとうございます。
Avatar
norio_nomura 5/10/2017 7:48 AM
swift-DEVELOPMENT-SNAPSHOT-2017-05-09-a 壊れまくりな感じ…
😩 1
Avatar
omochimetaru 5/10/2017 9:00 AM
swift-algorithm-club - Algorithms and data structures in Swift, with explanations!
9:00 AM
Raywenderlichすご・・・
9:02 AM
めちゃめちゃいろんなアルゴリズムのサンプル
9:03 AM
おい
9:03 AM
switch pattern matchじゃない
Avatar
Swift その2 の最後の 3 日が投稿されなかったので 3 連投です。 [当初のアナウンス](http://blog.qiita.c...
Avatar
omochimetaru 5/10/2017 9:04 AM
if i % 5 == 0 { result += (result.isEmpty ? "" : " ") + "Buzz" }
Avatar
PR投げてみようかな
Avatar
omochimetaru 5/10/2017 9:04 AM
3の場合と5の場合が合体してFizz Buzzになるのはそれはそれで良さがある
Avatar
↑多分 @tarunon さんが求めてるもの
Avatar
ですです
9:05 AM
なんかif分岐がいっぱいあるの
9:06 AM
どの場合にどこ通って最終的にどうなるっていうフローを見なきゃいけなくて
9:06 AM
辛いなって思うようになってしまった
Avatar
guard があるせいで else をちゃんとかくってのはありますねぇ
Avatar
omochimetaru 5/10/2017 9:06 AM
var がどうなってるか覚えながら読まないといけないよね
Avatar
そうそう
9:07 AM
siwtch (/*必要なもの全部ここにドーンwww*/) { case /*なんか条件いっぱい*/: return /*結果*/ /*以下繰り返し*/
9:08 AM
マジでこれ脳に優しい
Avatar
3の場合と5の場合が合体してFizz Buzzになるのはそれはそれで良さがある
FizzとBuzzをそれぞれ一度しか書かなくて良いのか
Avatar
omochimetaru 5/10/2017 9:08 AM
@koher そう
Avatar
FizzとBuzzの重複避けるにしてもまだ↓の方がいい。 func fizzBuzz(_ numberOfTurns: Int) { for i in 1...numberOfTurns { var fizzOrBuzz = false if i % 3 == 0 { print("Fizz", terminator: "") fizzOrBuzz = true } if i % 5 == 0 { print((fizzOrBuzz ? " " : "") + "Buzz", terminator: "") fizzOrBuzz = true } if !fizzOrBuzz { print(i, terminator: "") } print() } }
Avatar
omochimetaru 5/10/2017 9:16 AM
まあfizzbuzzはおまけで、文字列探索とかランレングスとか線形回帰とかいろんな木があってすごいって思いました
Avatar
result += (result.isEmpty ? "" : " ") + "Buzz" はさすがにひどい
Avatar
転する時に役に立ちそうなレポジトリですね(直喩)
Avatar
omochimetaru 5/10/2017 9:18 AM
カンニングはいかんぞ
Avatar
ここはチェックするようにしとこ
Avatar
ソースだけじゃなくて解説まで書いてあるw https://github.com/raywenderlich/swift-algorithm-club/tree/master/Quicksort
swift-algorithm-club - Algorithms and data structures in Swift, with explanations!
Avatar
omochimetaru 5/10/2017 9:18 AM
うん 行列のところとか カラフルだった
9:18 AM
9:19 AM
Avatar
数字の組を色とスタイルで表現してるのか
9:19 AM
優しい
9:20 AM
N社も見習ってイカにスクリーントーンいれてくれ!
Avatar
Authors: Rintaro Ishziaki
10:43 AM
オーサーがタイポされとる
Avatar
@rintaro 今ってまだ新しい Proposal が受け付けられてるフェーズなんですか?こういう議論の余地なしで実装ファーストなものだったら OK ?イマイチ swift-evolution の空気がよくわからない・・・。
Avatar
正直 ノリはまったくわかりません 😅
Avatar
おお、 rintaro さんでもわからないんですね 😅
Avatar
まったく根回しとかしてないので、どうなんでしょうねぇ
Avatar
実装もあるし、内容的にもイケそうな気も。
10:53 AM
ってか、そんな仕様だったんですね。むしろバグ?
Avatar
需要は間違いなくあるはず。
Avatar
内容自体は OK で、今の時期に Swift 4 に取り込むのが OK なのかですよね。 (edited)
10:56 AM
まさに↓な感じ。
I hope this makes it through without generating a lot of extra discussion. I would love to have this in Swift 4, or the next regular update of xcode.
Avatar
とりあえず stdlib ではいまのところ #if swift(>=4.0) で enum case 追加みたいなのがないので、微妙なんですが、 https://github.com/apple/swift/blob/master/stdlib/public/core/HashedCollections.swift.gyb#L4348-L4349 の Linux には存在しないはずの case cocoa(CocoaBuffer) の扱いをみてると泣きたくなったので実装しちゃいました。
swift - The Swift Programming Language
😀 1
Avatar
ついこの間# !TARGET_INTERFACEBUILDER出来なくて😇したので凄くタイムリーだ。ありがとうございます!
😀 1
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
10:32 PM
ちゃんと読んでないけど Carthage っぽくなるのかな?
10:34 PM
Carthage でも resolve コマンドほしいとずっと思ってた。
10:36 PM
色んな言語の Package Manager が dis られてるw
However, we think that a "lockfile" is a very poor name for this concept
Avatar
omochimetaru 5/11/2017 1:00 AM
ピンは消えたけど常にリゾルブドはできるようになる?
1:03 AM
流し読みじゃよくわからなかったからもう一度読んでみる
Avatar
omochimetaru 5/11/2017 1:22 AM
トップリポジトリに.resolvedが入ってれば同じ環境、ignoreしてればそれぞれその時の指定をみたす最新で解決
1:23 AM
でなんかそれとは別に個別の依存指定をみたすように修正するためにeditで編集モードに入ってなんたらかんたら
1:25 AM
これまでのpin仕様では個別にpinがあってデフォルトがpinされていて、何かやるにはunpinしたりする必要があって、混ざってややこしいから、解決したいのか完全固定したいのかの2つの要望をresolvedの有無で排他的に選択できるようにすればシンプルでいい
1:26 AM
みたいな話が書いてあるけどもともとのpinの仕様をちゃんと知らないからよくわからなかった。
Avatar
昨日の @rintaro さんの Proposal 、 Apple の中の人のコメントでも↓だから、何を evolution に通すべきなのかの明確な基準はなくて、コアチームの判断に委ねられているということかな? I'm in favor, certainly. I'd personally say this wouldn't even need to go through the full evolution process, but I'm not a core team member.
1:34 AM
Joe Groff も Seems reasonable to me. って言ってるしイケそう。
1:40 AM
Core Team メンバー自ら新しい提案を投げてるし、 swift-evolution のステータス謎。 https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170508/036582.html
Avatar
omochimetaru 5/11/2017 1:42 AM
この提案おもしろいな
1:42 AM
Characterは書記素クラスタだからUnicodeScalarの列とみなせるのか
1:42 AM
言われてみればできなきゃおかしいね
Avatar
この Ben Cohen さんって新しく Core Team メンバーになったんだけど、 Airspeed Velocity の中の人だったのか。
1:43 AM
airspeedswift has 9 repositories available. Follow their code on GitHub.
Avatar
Arrayをポインタで走査したい場合にCoWを走らせる方法って無いですかね? isKnownUniquelyReferencedで分岐できると良いんですが使えないようで。
2:12 AM
var a = [Int](repeating: 0, count: 10) var b = a let p = UnsafeMutablePointer<Int>(mutating: b) p.pointee = 100 // aも書き換わる
Avatar
omochimetaru 5/11/2017 2:12 AM
isKnownUniquelyReferencedはArray自体じゃなくて
2:12 AM
Arrayの中にあるバッファ(これは参照型ヒープオブジェクト)
2:13 AM
のはなしだよ。
Avatar
そこは分かってます。
Avatar
omochimetaru 5/11/2017 2:13 AM
はい
2:13 AM
あー、aとbを明示的にコピーしたいのか
Avatar
その上で外側にも使えたらコピーするかの分岐をこちらでできるなと
Avatar
omochimetaru 5/11/2017 2:13 AM
そのコードおもしろいな。
2:13 AM
コピーコンストラクタに渡したらどうですか?
Avatar
var a = [Int](repeating: 0, count: 10) var b = Array(a) let p = UnsafeMutablePointer<Int>(mutating: b) p.pointee = 100 print(a) print(b) [100, 0, 0, 0, 0, 0, 0, 0, 0, 0] [100, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2:14 AM
ん?
2:15 AM
そういえばArray(a[0..<a.count])でもコピーできてないんでした。
Avatar
omochimetaru 5/11/2017 2:15 AM
あれ?CCtorでもだめなのか
Avatar
iterator渡してるだけだから
2:16 AM
ダメなのでは
Avatar
omochimetaru 5/11/2017 2:16 AM
Array(a[0..<a.count]) マジ?ARraySliceからArray化は明示的コピーのはずなのに・・・?
Avatar
ArraySliceが全体を指してる場合のみの振る舞いっぽいですね
Avatar
omochimetaru 5/11/2017 2:17 AM
a
2:17 AM
a.withUnsafeMutableBufferPointer は?
2:18 AM
public mutating func withUnsafeMutableBufferPointer<R>(_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R) rethrows -> R
2:18 AM
これはmutatingメソッドだからCOWが生じるはず
2:19 AM
ネストしちゃう点についてはクロージャ内の処理だけ別のメソッドに切り出すとか?
2:19 AM
このアプローチならSwiftのセマンティクスとしても変な事はしてない (edited)
Avatar
UnsafeMutableBufferPointerだといけますね。ありがとうございます。
Avatar
var ary = [1,2,3] ary.withUnsafeMutableBufferPointer { buf in print(ary.count) // -> 0 } この挙動おもしろいな。
Avatar
omochimetaru 5/11/2017 2:26 AM
!?
2:27 AM
ほんとうだ・・・
Avatar
body 内でArray操作されないように 一時的に self を書き換えてる。 https://github.com/apple/swift/blob/master/stdlib/public/core/Arrays.swift.gyb#L1758-L1773
swift - The Swift Programming Language
Avatar
omochimetaru 5/11/2017 2:28 AM
おー
2:28 AM
いまオーナーシップマニフェスト読んでる途中なんですけど
2:28 AM
こういうのがまさに
2:28 AM
現状のmutable参照を共有する場合に対する保守的な余計なロジックっぽい
Avatar
https://github.com/apple/swift/blob/master/stdlib/public/core/Arrays.swift.gyb#L1085 initこれですよね、Bufferを渡すときに同型(Array)なら同じものが渡るようになってるのかしら(つまりCoWの範疇になる?)
swift - The Swift Programming Language
2:35 AM
swift - The Swift Programming Language
Avatar
omochimetaru 5/11/2017 3:30 AM
Resilience(レジリエンス)について理解しないといろいろな事が深くわからないなあと最近思っていて
3:31 AM
でもあんまり話題に出ないのと、語としても見慣れない
Avatar
norio_nomura 5/11/2017 3:39 AM
swift-DEVELOPMENT-SNAPSHOT-2017-05-09-a 壊れまくりな感じ…
swift-DEVELOPMENT-SNAPSHOT-2017-05-10-a で直ってた。
(edited)
🙂 1
Avatar
@omochimetaru Proposal の "Effect on API resilience" の Resilience ?
Avatar
omochimetaru 5/11/2017 5:09 AM
そこにも出てきますね
5:09 AM
最近は 既存のコードえの影響とresilienceへの影響が並んでますね。
Avatar
Error Handling Rationale and Proposal の方に出てた Resilience は、修正に対してどれだけ柔軟性(許容性?)があるかみたいな概念だと理解してました。
Avatar
omochimetaru 5/11/2017 5:10 AM
そういう一般的な概念じゃなくて、ABI互換性とかの周辺の具体的な議論な気がしている
Avatar
Proposal の雛形には API resilience describes the changes one can make to a public API without breaking its ABI. Does this proposal introduce features that would become part of a public API? If so, what kinds of changes can be made without breaking ABI? Can this feature be added/removed without breaking ABI? For more information about the resilience model, see the library evolution document in the Swift repository.
5:11 AM
って書かれてる。
5:11 AM
リンクされてるドキュメント( "see the library evolution document in the Swift repository" )は↓ https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst (edited)
swift - The Swift Programming Language
5:12 AM
アーカイブフォルダのなかにそのまんまな文書もあるけどアーカイブなのが気になる
5:13 AM
resilience model, see the library evolution document < ってかいてあるなら
5:13 AM
そこを読むのがまずは一番良さそうだ。
Avatar
omochimetaru 5/11/2017 3:17 PM
https://github.com/omochi/swift-ownership-jp/blob/master/ownership-manifesto.md オーナーシップマニフェストを読みました。読み飛ばさないでちゃんと読みたかったので、全文を和訳しました。まだ読んでない人は良かったら参考にしてください。あと変なところは僕も自分でよくわからなかった部分なので助けてくれると嬉しいです。
Contribute to swift-ownership-jp development by creating an account on GitHub.
❤ 6
👍 1
Avatar
これコンパイル通るんだな 通らないで欲しい struct Hoge { var fuga: Int { return fuga } } let hoge = Hoge.init() print(hoge.fuga) // <- 無限ループで死
Avatar
omochimetaru 5/12/2017 1:18 AM
たまにやらかすけどスタックトレースですぐわかる
Avatar
fuga以外のところで条件回して終端のある再起を書けるっちゃ書けるので、弾くのは難しいかしら
Avatar
そっかあ
Avatar
omochimetaru 5/12/2017 1:22 AM
fuga自体がループしてることはフロー解析で確定できると思う
Avatar
ループがエンドレスかどうかを証明するのは無理じゃね
Avatar
こんなん書いてて最初なんで死ぬのか気づかなかった private let _event: PublishSubject<Event> var event: Observable<Event> { return event.asObservable() }
Avatar
omochimetaru 5/12/2017 1:23 AM
一般の停止性判定ができないだけで、あるケース単体について証明できる場合はあるよ
Avatar
_eventあぶがないので、eventSubjectとかにした方が良い
Avatar
なるほど
Avatar
つまり、証明できる範囲についてコンパイルを通さない、なら可能か
Avatar
omochimetaru 5/12/2017 1:25 AM
そう。
Avatar
でも中途半端っぽい
Avatar
omochimetaru 5/12/2017 1:25 AM
うん。
1:25 AM
複数のプロパティが絡んだ相互再帰とか
1:25 AM
一見無限再帰してるけど、クラスだからオーバーライドすればカットできるとか
1:25 AM
ちょっと複雑でループするケースとかしない場合があるが実行するとループになるケースとか
1:25 AM
同種のバグで潰せないものはたくさん残る
Avatar
それさ
1:26 AM
証明可能なもの=人間にもすぐ見つけられる
Avatar
omochimetaru 5/12/2017 1:26 AM
でもhirariが踏んでる最も単純なパターンぐらいは対応してもいいかもね
Avatar
だからやる意味ほぼないでは?
1:26 AM
いやこれ、これでも
1:26 AM
単純でもループしない場合あり得そうな気がしていて
1:27 AM
ん?するか
1:27 AM
眠たかった
Avatar
omochimetaru 5/12/2017 1:27 AM
structだからオーバーライドできないからね
Avatar
眠たかったw
Avatar
omochimetaru 5/12/2017 1:29 AM
$ brew info carthege $ brew info carthego
1:29 AM
カルタゴ、スペルがわからなくなるからきらい
Avatar
hageだよ
Avatar
hageで覚える
Avatar
omochimetaru 5/12/2017 1:30 AM
そこ同じ回答来るのかよw
Avatar
ハゲカート
Avatar
omochimetaru 5/12/2017 1:30 AM
ハゲカートw
Avatar
これでおもち君は二度と忘れなくなった
Avatar
omochimetaru 5/12/2017 1:30 AM
そうだね・・・w
1:30 AM
解決した。
Avatar
carthage使う度にアイヴが脳裏にちらつく呪いをかけておこう
Avatar
omochimetaru 5/12/2017 1:31 AM
carthageのhageはアイブの禿か
Avatar
結局カルタゴとカッセージどっちが日本では主流なの
Avatar
omochimetaru 5/12/2017 1:32 AM
これでcartはfor steveの意味なら完璧だな。
1:32 AM
@hiragram ハゲカート主流にしよう
Avatar
気に入りすぎでしょ
Avatar
omochimetaru 5/12/2017 1:33 AM
はい
Avatar
日本人と口頭で日本語で会話するときはカルタゴって言ってて、英語のときはカッセージていってる
1:33 AM
かーせーじかな
Avatar
omochimetaru 5/12/2017 1:34 AM
トマトとトメイトウ
Avatar
タマゴとタメイゴウ
Avatar
😋 1
Avatar
omochimetaru 5/12/2017 1:34 AM
エッグだわ
🍆 1
1:37 AM
ちなみにさっきのコード、今気づいたけど警告出てた。
Avatar
omochimetaru 5/12/2017 1:37 AM
警告全部けそ
1:37 AM
ちゃんとなおして
Avatar
コンパイラが警告してくれてたなら全部人間が悪いな
1:38 AM
滅ぼう
😆 1
Avatar
主な変更内容 GitHub で見やすいように Markdown ファイルを README に変更 オリジナルへのリンクを追加 翻訳元バージョンのコミットへのリンクを追加 ライセンスへのリンクを追加 どこからが本文化わかりやすいように本文開始前の前書きの後ろに水平線を追加
Avatar
omochimetaru 5/12/2017 2:01 AM
お、ありがとうございました。マージした。
Avatar
@omochimetaru 思ったんだけど、元の文書を initial commit にしておけば、今後のオリジナルの変更をそれに対して加えて、それをマージすることで自動的に和訳中の英文も更新できた気がする。
2:16 AM
今からでも、できる気もする。
Avatar
omochimetaru 5/12/2017 2:17 AM
ブランチわけっぱなしにして3点間マージを維持するのか
Avatar
はい
Avatar
omochimetaru 5/12/2017 2:17 AM
基本的に追記しかしてないからうまくいくはずですね
Avatar
original ブランチを作って、そこに原文つっこんで
2:17 AM
originalmaster でマージして master の今のバージョンをそのまま採用して
2:17 AM
ってやればいけそう。
Avatar
norio_nomura 5/12/2017 2:41 AM
おや? swift-4.0-DEVELOPMENT-SNAPSHOT-2017-05-09-a が出てる。
2:42 AM
あいや swift-4.0-DEVELOPMENT-SNAPSHOT-2017-05-11-a だった。
Avatar
norio_nomura 5/12/2017 3:37 AM
Swift 4.0 でこんな変更が必要ぽいのだけど、これって SE-0110 Distinguish between single-tuple and multiple-argument function types https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.md の影響なのかな? func run(_ options: NoOptions<SourceKittenError>) -> Result<(), SourceKittenError> { print(version) - return .success() + return .success(()) }
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
おおお、面倒だけどわかりやすくはありますね・・・。
Avatar
型としての ()Void にすべき派。
👍 1
Avatar
omochimetaru 5/12/2017 4:33 AM
僕もどっちかといえば空タプルよりVoidのほうが好きです > 型としての () は Void にすべき派。
Avatar
自分は標準ライブラリとかだと () -> Void で定義されてるのでそっちで合わせてました
Avatar
omochimetaru 5/12/2017 4:41 AM
func f11(x: () -> ()) {} func f12(x: () -> Void) {} func f13(x: () -> (Void)) {} func f14(x: () -> ((Void))) {} func f15(x: () -> (((Void)))) {} func f21(x: (Void) -> ()) {} func f22(x: (Void) -> Void) {} func f23(x: (Void) -> (Void)) {} func f24(x: (Void) -> ((Void))) {} func f25(x: (Void) -> (((Void)))) {} func f31(x: ((Void)) -> ()) {} func f32(x: ((Void)) -> Void) {} func f33(x: ((Void)) -> (Void)) {} func f34(x: ((Void)) -> ((Void))) {} func f35(x: ((Void)) -> (((Void)))) {}
Avatar
((Void))は悪意を感じるw
Avatar
omochimetaru 5/12/2017 5:04 AM
@koher Diffにできた https://github.com/omochi/swift-ownership-jp/commit/02a3eab7b6a32bc8d58d963ec8758a7145330df6?diff=split このリポジトリにSE0716の和訳とか後に書くキータ記事も入れようと思ってるのでファイル名はREADMEから戻しました。 (edited)
👌 1
Avatar
norio_nomura 5/12/2017 7:27 AM
午前中に書いたコメントがforce pushの彼方に
Avatar
omochimetaru 5/12/2017 7:28 AM
すいません、何か見逃しちゃったのか
7:28 AM
あ、完全に initial からふっ飛ばしたから
7:29 AM
github上で見る方法がわからない・・・
Avatar
@omochimetaru Initial からやらなくても、孤立 commit 作ってそれを merge すればよかったのに・・・。 (edited)
Avatar
omochimetaru 5/12/2017 7:30 AM
孤立コミットはマージできなかった。
Avatar
え?できるでしょ?
7:30 AM
できないっけ??
Avatar
omochimetaru 5/12/2017 7:31 AM
[omochi@omochi-MB swift-ownership-jp (master=)]$ git merge original fatal: refusing to merge unrelated histories
Avatar
norio_nomura 5/12/2017 7:32 AM
まあ、僕が書いた場所が悪い。
Avatar
--allow-unrelated-histories つけてもダメでした?
Avatar
omochimetaru 5/12/2017 7:32 AM
@norio_nomura あ〜これ less .. than の形が読めてないですね ありがとうございます
🙂 1
7:33 AM
@moaible それは知らなかったです、いかにもできそうな名前
7:37 AM
ここは一個前の require が absolute よりも predictable であることを欲するよって
7:37 AM
話っぽいな
Avatar
Contribute to isolated-commit development by creating an account on GitHub.
7:37 AM
あ、まさにそれやって試してた
7:38 AM
$ git log --graph --all --decorate * commit 8959b3248ca9f6264f36a08d67d47e1cd1271d6f (HEAD -> master, origin/master) |\ Merge: 5494a14 773e8de | | Author: Yuta Koshizawa <koher@koherent.org> | | Date: Fri May 12 16:35:58 2017 +0900 | | | | Merge branch 'original' | | | * commit 773e8defca014cefed7d4aade63b9b22255772f5 (origin/original, original) | Author: Yuta Koshizawa <koher@koherent.org> | Date: Fri May 12 16:34:23 2017 +0900 | | Original | * commit 5494a1445902fcfa7aeaf3708a3f9c939f807647 Author: Yuta Koshizawa <koher@koherent.org> Date: Fri May 12 16:33:23 2017 +0900 Initial commit
7:38 AM
$ git diff original master diff --git a/a.txt b/a.txt index 1802a74..c4f3b1d 100644 --- a/a.txt +++ b/a.txt @@ -1,3 +1,6 @@ aaa +111 bbb +222 ccc +333
Avatar
omochimetaru 5/12/2017 7:38 AM
@koher --allow-unrelated-histories が必要だった?
Avatar
はい。
Avatar
omochimetaru 5/12/2017 7:39 AM
なるほど。
7:39 AM
基本的にforce pushしても
7:39 AM
コードコメントはPRとかについてるから
Avatar
コミット番号さえわかってれば、もう一度 force push して元に戻してもいいかも? (edited)
Avatar
omochimetaru 5/12/2017 7:39 AM
何も失わないと思っていた
7:45 AM
@koher あとでやってみます
Avatar
norio_nomura 5/12/2017 7:46 AM
わかりやすい
Avatar
omochimetaru 5/12/2017 7:51 AM
koherのPRをマージした直後の状態からはじめて、リネームをして、 オリジナルをおいて、その2つをマージして、そこから辻褄をあわせていけばいいのか
Avatar
オリジナルをおいたコミットは再利用できそう
Avatar
omochimetaru 5/12/2017 7:52 AM
あ、たしかに。
Avatar
norio_nomura 5/12/2017 8:08 AM
型としての () は Void にすべき派。
いい機会だから Void に変えようと試したら、ビルドできなかった。 error: member 'success' in 'Result<Void, SourceKittenError>' (aka 'Result<(), SourceKittenError>') produces result of type 'Result<T, Error>', but context expects 'Result<Void, SourceKittenError>' (aka 'Result<(), SourceKittenError>') return .success(Void) ^
(edited)
Avatar
Void はあくまで型なので、そのインスタンスは () しかだめですね。
Avatar
norio_nomura 5/12/2017 8:09 AM
ああ、なるほど。
8:11 AM
return .success(Void()) で通る。
Avatar
omochimetaru 5/12/2017 8:11 AM
知らんかったw
Avatar
Void()できるんだ
Avatar
omochimetaru 5/12/2017 8:11 AM
言われてみればという感じ
Avatar
あれ? Void って typealias じゃないの?
Avatar
できる。 typealias A = (a: Int, b: Int) let a = A(1,2) もできる。
Avatar
おー
Avatar
omochimetaru 5/12/2017 8:12 AM
!?
8:12 AM
なるほど・・・
Avatar
知らんかった
Avatar
でも.initで推薦してくれないですよね
Avatar
なんですよねー > .init
Avatar
推薦してくれたら色々捗る
Avatar
A(a: 1, b: 2) ではないんだ
Avatar
@hiragram どっちもいけるよ
8:13 AM
Tuple、ただただ.initで推薦してくれないのが本当に不便で、結局.initを書く必要がある場合はStruct作れ!ってなってる
Avatar
いけんのか
Avatar
4> typealias A = (a: Int, b: Int) 5> A(a: 2, b: 3) $R0: (a: Int, b: Int) = { a = 2 b = 3 } 6> A.init(a: 2, b: 3) error: repl.swift:6:1: error: type 'A' (aka '(a: Int, b: Int)') has no member 'init' A.init(a: 2, b: 3) ^ ~~~~
Avatar
いけてない?
Avatar
これはinitです
Avatar
おー
Avatar
initは無い。
Avatar
6> let createA: (Int, Int) -> A = A error: repl.swift:6:32: error: cannot convert value of type 'A.Type' (aka '(a: Int, b: Int).Type') to specified type '(Int, Int) -> A' let createA: (Int, Int) -> A = A ^
8:17 AM
.init もダメだし、変数に入れることはできないか・・・
8:17 AM
結局.initを書く必要がある場合はStruct作れ!ってなってる
タプルは用法用量を守って使うのがいい気がするから、本当に一時的なペアでない限り struct がいいと思います。
(edited)
Avatar
typealias A = (a: Int, b: Int) let a = A(a: 1, 2) let b: (x: Int, y: Int) = (1,y: 2) これが出来るのとか含めて、タプルは特別扱いすぎて本当に。
Avatar
norio_nomura 5/12/2017 8:20 AM
とりあえずさっきのは Void に変えるのはやめよう
Avatar
truefalse のノリで void があってもいい気もする。 Void 型のインスタンスが () なのはわかりづらい・・・。
Avatar
let void=Void()って書いておけばまぁ使えますねw
Avatar
かといって、 () 型のインスタンスが () なのも、値と型の区別がつきづらいけど・・・
Avatar
(良いかどうかは別として)
Avatar
ですね。
8:24 AM
うーん、結局 Void のインスタンスを扱わなければならないとき(ジェネリクスの型パラを Void で埋めたときなど)は Void 型のインスタンスを扱う必要があって、そうすると Void()typealias であることを知っている必要があって・・・と考えると、 Void より () と書いている方がいい気がしてきました。
8:25 AM
戻り値 Void はそもそも省略できるから書かないし。
Avatar
ジェネリクス型がVoidの場合に、extensionに引数を省略した関数群を提供するのは一つの手かなと思っています。 (edited)
😍 1
Avatar
なるほどー。 (edited)
8:28 AM
こんな感じで。
Avatar
omochimetaru 5/12/2017 8:28 AM
voidで型パラ埋めてる時は Voidの値 () を無駄に取る事の無い版を付け足すのか
Avatar
Swift 4 ってタプルが区別されるのは引数だけで↓はそのままなんですよね? 6> let a: Int = (((42))) a: Int = 42 7> let b: (((Int))) = a b: (((Int))) = { _value = 42 } 8> b + 1 $R1: Int = 43 (edited)
Avatar
要素数1の括弧はタプルではないのはそのままです。 (edited)
👌 1
Avatar
そうすると、 () -> ()(()) -> () は異なるのに () -> (()) は同じってちょっと気持ち悪い感じが・・・。
8:31 AM
まあしかたないですが・・・。
Avatar
((( ))) -> RetTy |-----| param list |---| paren |-| tuple って感じですね。 (edited)
👍 1
Avatar
paren が入ってくるあたりにも闇を感じますね・・・
8:34 AM
タプルの括弧が () なのよくないよなぁ。やっぱ @tarunon さんの言うように人類には括弧が足りなかった・・・
Avatar
{([<
8:35 AM
どう見ても足りないです本当に
Avatar
<, > も演算子と共用なのがヤバイですしね。
Avatar
「」←彼らをデビューさせましょう(ない)
Avatar
お、それなら 『』, 【】 もいけますねw
8:38 AM
それくらいあれば戦えそうだw
Avatar
問題は、入力可能じゃないところ。。。
Avatar
ASCIIに入ってないと戦力外ですからねぇ・・・
8:40 AM
Array【Int】 とか、可読性だけならアリそう。
Avatar
omochimetaru 5/12/2017 8:40 AM
<<{ }>> <<( )>> <<[ ]>> みたいな合体で意味を変えて増やす
Avatar
@omochimetaru 地獄の始まりでしょw
Avatar
┗( )┛
8:41 AM
イシツブテ
Avatar
┗("o")┛ 顔っぽくなるぞ
Avatar
合体で意味を変えて増やす、Objcのブロック構文の二の舞いだし絶対ダメだと思う
Avatar
このサイトにはお世話になりました http://fuckingblocksyntax.com/
Avatar
以前どこかで初期化なしでFloat配列を作りたいって話で聞いた方法をずっと使ってたんですが 今急にコピーコスト考えるとそっちのが高いんじゃと思って試してみたらやっぱり遅かった…… func testA() { let size = 10_000_000 measure { // 0.013sec let array = [Float](repeating: 0, count: size) } } func testB() { let size = 10_000_000 measure { // 0.034sec let dst = UnsafeMutablePointer<Float>.allocate(capacity: size) defer { dst.deallocate(capacity: size) } let array = [Float](UnsafeBufferPointer(start: dst, count: size)) } }
Avatar
omochimetaru 5/12/2017 9:42 AM
array = のところの右辺のコンストラクタ呼び出しで
9:43 AM
結局全要素をコピーしてる?
Avatar
だと思います
Avatar
omochimetaru 5/12/2017 9:43 AM
UnsafeBufferPointerのまま
9:43 AM
それを配列的につかえば
9:43 AM
そのコストは消せそう
Avatar
うーんでも
9:43 AM
deferで開放されるわけですし
Avatar
omochimetaru 5/12/2017 9:43 AM
UnsafebufferPointerもMutableCollectionじゃなかったっけ。
Avatar
ああそういうことですか
Avatar
omochimetaru 5/12/2017 9:44 AM
Array型を使わないってこと。
Avatar
それは一理ありますね
9:46 AM
ただUnsafeBufferPointer自体をそのまま作ることはできないので開放タイミングがどうすればいいのかさっぱり分からないという
9:46 AM
UnsafeBufferPointerの持ち主のdeinitで開放させるとかになるんですかね
Avatar
omochimetaru 5/12/2017 9:48 AM
/// An UnsafeBufferPointer instance is a view into memory and does not own the memory /// that it references.
9:48 AM
UnsafeBufferPointerはメモリ空間へのビューを提供するだけでそれ自身はメモリ領域を保持しないから
9:49 AM
引数で与えたポインタの所有権はいまだプログラマ側にある
9:49 AM
func testB() { let size = 10_000_000 measure { // 0.034sec let dst = UnsafeMutablePointer<Float>.allocate(capacity: size) defer { dst.deallocate(capacity: size) } let array = UnsafeBufferPointer(start: dst, count: size) } }
9:49 AM
↑さっきのコードで言えばこうするだけ
Avatar
速度自体はこれが圧倒的ですね あとはメモリ管理の煩雑さを受け入れるかどうか……
Avatar
omochimetaru 5/12/2017 9:50 AM
自分で作ればいいんじゃない?
9:50 AM
↑の let dst = を initの中で呼び出して
9:50 AM
defer { } の中を deinit で呼び出す
9:50 AM
structを作れば
Avatar
その考えはなかった
9:51 AM
それでちょっとやってみます。
Avatar
omochimetaru 5/12/2017 9:51 AM
あ、structにはdeinitかけないから、classでかいて structでラップする必要があるね・・・
9:51 AM
まあclassでかいて let で受けてもいいです
Avatar
Contribute to swift-ownership-jp development by creating an account on GitHub.
10:21 AM
というわけで、SE0176も訳しました。こっちのほうがまともな日本語になっている感。 https://github.com/omochi/swift-ownership-jp/blob/master/0176-enforce-exclusive-access-to-memory.md (edited)
Contribute to swift-ownership-jp development by creating an account on GitHub.
Avatar
@t.ae 結局クラスつかうんだったら、 ManagedBuffer のほうが良いと思いますよ。
Avatar
お、そのクラスは知らない
11:02 AM
おお〜〜
Avatar
バッファが ManagedBuffer のオブジェクトの実体の直後に tail allocate されるので、ちょっとだけ効率が良いはず。
Avatar
ポインタジャンプが1回少ないってことですか?
Avatar
これはいいですね。ありがとうございます!
Avatar
ポインタジャンプが1回少ない
のはず。
👏 1
11:12 AM
ただ、オブジェクトの起点から テールアロケートされたところまでのポインタ計算が一回入るはずなので、そんなにパフォーマンスは変わらないかもです。
Avatar
オフセット計算が入るのはそうですが、ヒープアロケーション/でアロケーションが1回減るのは大きいし、アドレスが離れた場合のキャッシュ効率も変わるので結構変わりそう
Avatar
https://developer.apple.com/reference/swift/managedbuffer
Typical usage stores a count and capacity in Header and destroys any live elements in the deinit of a subclass.
サブクラス作ってdeinit呼ぶ必要があるのでは?
Avatar
そうなんですが、 T が Float などの trivial な値だったらそのままでも大丈夫かと。
Avatar
なるほど
11:17 AM
https://gist.github.com/airspeedswift/1fb7d6e3e73e53ce64f6 別の実装見つけてたんですがこっちはGenericだからですね
Array using ManagedBuffer
Avatar
Patient: Doctor doctor, it hurts when I do this. Doctor: Well, don’t do that. On twitter, I wrote: Your reminder that building arrays with reduce, while fun, is accidentally quadratic. I was surpri…
Avatar
ContiguousArray 使えばいいのでは?と思ってしまう。
Avatar
@norio_nomura 大本の僕の目的はArrayの初期化コストを削減したいということなのです
Avatar
Array の初期化コストが hot spot なのですか?
Avatar
今やってるプログラム上でコストが思いかどうかまでは検討してないです。
12:37 PM
ちょっと要点抜き出して書いて確かめてみます
12:41 PM
func testA() { let size = 10_000_000 let src = [Float](repeating: 0, count: size) var one: Float = 1 measure { // 0.020sec var dst = [Float](repeating: 0, count: size) vDSP_vsadd(src, 1, &one, &dst, 1, vDSP_Length(size)) } } func testB() { let size = 10_000_000 let src = [Float](repeating: 0, count: size) var one: Float = 1 measure { // 0.017sec let dst = UnsafeMutablePointer<Float>.allocate(capacity: size) defer { dst.deallocate(capacity: size) } vDSP_vsadd(src, 1, &one, dst, 1, vDSP_Length(size)) } } ほとんど差ないですね
12:42 PM
これなら初期化させていいか……
Avatar
15%も違うなら結構でかいのでは
12:44 PM
ただ、テスト条件が
12:44 PM
あまり現実的じゃないから
12:44 PM
ヒープアロケーションのコストとか
12:44 PM
特性が変わっちゃうのでは
12:44 PM
現実的なサイズの行列を何度も計算した時の
12:44 PM
性能を評価しないと意味なさそう
Avatar
実用でここまでのサイズか微妙ですし、実際はこの他にコストが重そうなところがあるんですよね
Avatar
ふむ
Avatar
func testA() { let size = 10_000 let src = [Float](repeating: 0, count: size) var one: Float = 1 measure { // 0.021sec for _ in 0..<size { var dst = [Float](repeating: 0, count: size) vDSP_vsadd(src, 1, &one, &dst, 1, vDSP_Length(size)) } } } func testB() { let size = 10_000 let src = [Float](repeating: 0, count: size) var one: Float = 1 measure { // 0.012sec for _ in 0..<size { let dst = UnsafeMutablePointer<Float>.allocate(capacity: size) defer { dst.deallocate(capacity: size) } vDSP_vsadd(src, 1, &one, dst, 1, vDSP_Length(size)) } } } これだと倍近い差が
Avatar
大きいね
Avatar
norio_nomura 5/12/2017 1:27 PM
あれ?比較対象は ManagedBuffer を使った型ではないのね。
Avatar
大体同じだと思ったんで というかそこまで気が回ってなかったです
1:30 PM
いちおう試してみましたけどほぼ同じですね
Avatar
norio_nomura 5/12/2017 1:41 PM
なるほど、あとは書いたデータの読み出し?
Avatar
読み出し回数は比較的少なくなる予定です。
1:45 PM
のでO(1)じゃなくても書き込みほど影響は大きくないかと
1:48 PM
逆にシーケンスとかで初期化したいときのコストが気になりそうな
Avatar
norio_nomura 5/12/2017 2:02 PM
Instrumentsで見ると、 var dst = ContiguousArray<Float>(repeating: 0, count: size) dst.withUnsafeMutableBufferPointer { dst in vDSP_vsadd(src, 1, &one, dst.baseAddress!, 1, vDSP_Length(size)) } でもUnsafeMutablePointerとほぼ同じになるぽい。 (edited)
2:05 PM
measure の結果は遅くなるのに。
Avatar
こちらもmeasureで遅くなりました
Avatar
最近swiftのswift-4.0-branchをビルドしようとしてるんですけど下記のエラーでうまくいかないのですが、単に壊れるコミットなのか、それとも何か見逃しているんでしょうか (edited)
12:09 PM
build error
7.71 KB
12:14 PM
あ、 !535 は 535 utils/build-script --skip-ios --skip-tvos --skip-watchos --jobs 2 --skip-test-osx true
Avatar
https://ci.swift.org/view/swift-4.0-branch/ でビルドできてるコミットを使ってみるとか。 (edited)
Avatar
@norio_nomura なるほど!やってみます。
Avatar
あ、スナップショットが出てるから、
12:17 PM
そのタグをビルドしてみるのが良いかな。
Avatar
ふむ
12:18 PM
swift-4.0-DEVELOPMENT-SNAPSHOT-2017-05-11-a
12:18 PM
これか
Avatar
utils/update-checkout --scheme swift-4.0-branch --tag swift-4.0-DEVELOPMENT-SNAPSHOT-2017-05-11-a でチェックアウト
Avatar
gitでswiftのリポジトリをチェックアウトしたあとに utils/update-checkout でも同じですか? (edited)
Avatar
swift以外のリポジトリも同じタグをチェックアウトしないといけないです。
Avatar
あら、連動してチェックアウトするのが utils/update-checkout ってわけじゃないんですね。
12:20 PM
とりあえず、そのコマンドでやってみます
Avatar
オプションなしで utils/update-checkout を実行した結果がどうなるかは知らないです。
Avatar
なるほど。
Avatar
omochimetaru 5/13/2017 1:57 PM
うーむおなじだ
1:57 PM
/Users/omochi/work/swift-source/swift/lib/Basic/Version.cpp:334:5: error: static_assert failed "getCurrentLanguageVersion is no longer correct here" static_assert(SWIFT_VERSION_MAJOR == 4, ^
Avatar
$ utils/update-checkout --clone --scheme master とりあえず master 前提で進めると、これで関連リポジトリ含めて全て clone してきます。 (edited)
2:05 PM
で、今エラー出てるのは、ビルドディレクトリに変なファイルが残っちゃっているからだと思うので
2:06 PM
$ utils/build-script --clean ... のように --clean オプション付けて build-script 実行
2:09 PM
過去にビルドしたことあるなら https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20170424/004482.html でアナウンスされているとおり、 --clean ビルドが必要です。
👍 1
Avatar
norio_nomura 5/13/2017 2:16 PM
ああ、そのエラーどこかで見たと思ったら、そのアナウンス前後だ。
Avatar
omochimetaru 5/13/2017 2:29 PM
やってみます!
Avatar
omochimetaru 5/14/2017 5:14 AM
@rintaro cleanのおかげでビルドできました。ありがとうございます。
Avatar
norio_nomura 5/14/2017 5:44 AM
swift-4.0-DEVELOPMENT-SNAPSHOT-2017-05-13-a が来そうな感じ ダメだった (edited)
Avatar
class A<X> { } class B: A<B.X> { struct X {} } print(B())
9:56 AM
↑コンパイルは通るけど実行時に無限に停止する
9:56 AM
もう報告されてるかな。
Avatar
デッドロックしてるぽいね。 (lldb) bt * thread #1, name = 'test', stop reason = signal SIGSTOP * frame #0: 0x00007ffff6a72a9f libpthread.so.0`__pthread_once_slow + 95 frame #1: 0x00007ffff7c7f96f libswiftCore.so`swift_once + 95 frame #2: 0x0000000000400fef test`type metadata accessor for test.B + 47 frame #3: 0x0000000000401531 test`___lldb_unnamed_symbol7$$test + 17 frame #4: 0x00007ffff6a72ae9 libpthread.so.0`__pthread_once_slow + 169 frame #5: 0x00007ffff7c7f96f libswiftCore.so`swift_once + 95 frame #6: 0x00000000004013df test`type metadata accessor for test.B.X + 47 frame #7: 0x000000000040138e test`type metadata accessor for test.A<test.B.X> + 30 frame #8: 0x0000000000401341 test`___lldb_unnamed_symbol5$$test + 17 frame #9: 0x00007ffff6a72ae9 libpthread.so.0`__pthread_once_slow + 169 frame #10: 0x00007ffff7c7f96f libswiftCore.so`swift_once + 95 frame #11: 0x0000000000400fef test`type metadata accessor for test.B + 47 frame #12: 0x0000000000400f31 test`main + 65 frame #13: 0x00007ffff6ca1830 libc.so.6`__libc_start_main + 240 frame #14: 0x0000000000400e09 test`_start + 41
Avatar
omochimetaru 5/15/2017 1:33 AM
@norio_nomura さんが前言っていたみたいに、自前ビルドのswiftをXcodeのToolchainsに入れるのってどうやるんですか?あと、そういう系の情報ってどの文書に書いてありますか? build-script -h は見たけど書いてなかったのと、ビルドにも時間かかりすぎて試行錯誤ができず・・・
1:33 AM
swift-source/build/Ninja-Release/swift/bin とかにバイナリが入ってるところまではいけたんですが。 (edited)
Avatar
norio_nomura 5/15/2017 1:47 AM
僕は swift/utils/build-toolchain を使いました。このジョブと同じ内容。 https://ci.swift.org/view/Packages/job/oss-swift-package-osx/ (edited)
1:49 AM
ですが、 swift-nightly-install ディレクトリ内にツールチェイン一式が出来ていれば、インストーラパッケージを作れるはず。
1:50 AM
swift/utils/build-toolchain はすべてのプラットフォームのテストを実行するため、めっちゃ時間がかかります。(僕のMacで11時間以上かかった)
Avatar
omochimetaru 5/15/2017 1:50 AM
Job config: swift/utils/build-script --preset="buildbot_osx_package" \ install_destdir="${SWIFT_INSTALL_DIR}" \ installable_package="${SWIFT_INSTALLABLE_PACKAGE}" \ install_toolchain_dir="${SWIFT_TOOLCHAIN_DIR}" \ install_symroot="${SWIFT_INSTALL_SYMROOT}" \ symbols_package="${SYMBOLS_PACKAGE}" \ darwin_toolchain_bundle_identifier="${BUNDLE_IDENTIFIER}" \ darwin_toolchain_display_name="${DISPLAY_NAME}" \ darwin_toolchain_xctoolchain_name="${TOOLCHAIN_NAME}" \ darwin_toolchain_version="${DARWIN_TOOLCHAIN_VERSION}
1:51 AM
これらのパラメータはどうやって決めました? (edited)
1:52 AM
swift-nightly-install というディレクトリは見当たらないです
1:52 AM
iOS向けとかをskipしてると駄目なのかな
Avatar
norio_nomura 5/15/2017 1:52 AM
CIログの前半に、実際のサンプルが出て来ます。 https://ci.swift.org/view/Packages/job/oss-swift-package-osx/3373/consoleText
1:55 AM
^改行入れた
Avatar
omochimetaru 5/15/2017 1:56 AM
ありがとうございます、なるほど、CIの詳細を見ればいいわけですね
Avatar
norio_nomura 5/15/2017 1:56 AM
そそ。
Avatar
omochimetaru 5/15/2017 1:56 AM
↑こういうのはみつかったけどnorioさんがはってるやつはどこからいけるんですか?
1:57 AM
a
1:57 AM
あった
1:57 AM
「プレーンテキスト表示」か
Avatar
norio_nomura 5/15/2017 1:57 AM
そそ
Avatar
omochimetaru 5/15/2017 1:58 AM
おとなしくフルビルドしたら24時間かかりそうなんだよな・・・
Avatar
norio_nomura 5/15/2017 1:59 AM
で、インストーラ作成もCIログを見ればわかりますが、僕はこんなスクリプトにしてます。 https://gist.github.com/norio-nomura/185a61fd93b6a6d275f0445bcb4be6d0
swift/swift-nightly-install からインストーラパッケージを作成
1:59 AM
--skip-test-* なんとかをつけまくれば良いと思います。>テスト (edited)
2:01 AM
Avatar
omochimetaru 5/15/2017 2:03 AM
ふむふむ
Avatar
norio_nomura 5/15/2017 2:04 AM
11時間以上は MacBook Pro (Retina, 13-inch, Late 2013) 2.6 GHz Intel Core i5 8 GB 1600 MHz DDR3 での結果。
Avatar
omochimetaru 5/15/2017 2:04 AM
MacBook (Retina, 12-inch, Early 2015) 1.3 GHz Intel Core M
2:05 AM
だいたいそれの4倍かかるw
Avatar
norio_nomura 5/15/2017 2:06 AM
各プラットフォームのテストが圧倒的に長いので、osxとios simulator以外をスキップすれば、かなり短縮できると思う。
Avatar
omochimetaru 5/15/2017 2:07 AM
なるほど。 --skip-ios --skip-tvos --skip-watchos 現状これで6時間とかです
Avatar
norio_nomura 5/15/2017 2:07 AM
昨日のフルビルド?
Avatar
omochimetaru 5/15/2017 2:07 AM
はい
2:07 AM
4時間かな?
2:08 AM
consoleText、chromeが死ぬので今テキストエディタで開きました。。
Avatar
norio_nomura 5/15/2017 2:09 AM
各リポジトリ間の依存が問題なければ、swiftだけ最新にして、テストもswiftだけにして、他のリポジトリのテストもスキップとかすれば良いのかも。
Avatar
omochimetaru 5/15/2017 2:10 AM
CIログと build-script-impl の冒頭を見比べたらいろいろできそうなのでやってみます
Avatar
norio_nomura 5/15/2017 2:11 AM
あ、僕の11時間はlldbのテスト含んでたので、--skip-test-lldb をつけるとさらに短縮されるかな。
Avatar
omochimetaru 5/15/2017 2:11 AM
skip-test-lldb とかはでかそうですね
Avatar
norio_nomura 5/15/2017 2:12 AM
最新のスナップショットは、lldbのテストが通らないので --skip-test-lldb で出てるはず。
Avatar
omochimetaru 5/15/2017 2:12 AM
そういうこともあるのか・・・
Avatar
norio_nomura 5/15/2017 2:20 AM
Appleのlldbチームの人が大勢やめたとかそんな話を見かけたけど、真偽未確認…
Avatar
omochimetaru 5/15/2017 2:22 AM
フーム
2:22 AM
テスラはSwift関係者引き抜くのやめてほしい
Avatar
いや、 Apple の外に Swift が飛び出すことによって、より広い範囲で使われるようになるかもしれない。
2:27 AM
Swift が汎用メジャー言語になるためには「 Apple の言語」ではダメで、影響力のある会社が何社か iOS 以外の実案件で採用してくれないといけないと思う。テスラがそうなるかはわからないけど。
Avatar
これ、こういうことがしたいんだけど書き方間違ってるか出来ないか分かる人いますか struct Hoge<T> { } extension Hoge where T == [Any] { func fuga() -> T.Element { // <- Error: 'Element' is not a member type of 'T' fatalError() } }
Avatar
omochimetaru 5/15/2017 2:34 AM
答えにはならないけど その場合なら Any って書けば?
Avatar
あー、
Avatar
omochimetaru 5/15/2017 2:36 AM
struct Hoge<T> { } extension Hoge where T: Sequence { func fuga() -> T.Iterator.Element { // <- Error: 'Element' is not a member type of 'T' fatalError() } } これは通るね
2:36 AM
ConcreteTypeでのEquality Constraintの時には左辺値に型定義が伝搬しない・・・?
Avatar
あれ、これだと例えば Hoge<[Int]> にはこのextensionだめ?
Avatar
omochimetaru 5/15/2017 2:36 AM
だめだと思うよ。
Avatar
任意の配列を型パラに持つとき、その配列の要素の型を返すメソッドみたいなのを生やしたいみたいな感じなんだけどにゃあ…
Avatar
omochimetaru 5/15/2017 2:37 AM
それは型パラ付きExtensionが必要だけど今無い、って話しな気がする
2:37 AM
extension定義自体が <T> を取る必要がありそう
Avatar
なるほど。
Avatar
omochimetaru 5/15/2017 2:39 AM
@koher 今影響力の大きい適応範囲だとサーバサイドLinuxとブラウザとAndroidっすね
Avatar
where付きのextensionの中でそのTが[Any]に見えないってことなの
2:40 AM
struct Hoge<T> { } struct Nested { struct MoreNested { } } extension Hoge where T == Nested { func fuga() -> T.MoreNested { // これもだめだった。 fatalError() } }
Avatar
omochimetaru 5/15/2017 2:40 AM
struct Hoge<T> { } extension Hoge where T == Array<Any> { func fuga() { print("fuga!") } } let x = Hoge<[Int]>() x.fuga()
2:40 AM
Playground execution failed: error: HogeGround.playground:5:1: error: 'Hoge<[Int]>' (aka 'Hoge<Array<Int>>') is not convertible to 'Hoge<Array<Any>>' x.fuga()
2:41 AM
あーそうか、理論的にも無理だわな
Avatar
[Any]と[Int]はだめか
Avatar
omochimetaru 5/15/2017 2:41 AM
Array<Int> is Array<Any> だけど、 Hoge<Array<Int>> は Hoge が T について Covariance でないかぎり Hoge<Array<Any>> ではない。
Avatar
↑のNestedとMoreNestedのやつはなんか直感的にそれでいけるもんだと思ってたんだけど行けなかった悲しい
Avatar
omochimetaru 5/15/2017 2:43 AM
まー == はなんか本当に代入されるわけじゃないっぽいね。
Avatar
このチャンネルで 5/2 に @koher さんがそれ的なことをやりたくて @norio_nomura さんによる workaround 出てるので、ログ見てみてください。
Avatar
お、見てみます。
Avatar
まじすか。全然記憶にないw
Avatar
パーマリンク欲しいなぁ。
😐 1
Avatar
omochimetaru 5/15/2017 2:43 AM
structのvarianceの話なんか過去にありましたね
Avatar
たださ、Xcodeちゃん、 -> T. まで打つと NestedType を補完してくるんだよな
Avatar
omochimetaru 5/15/2017 2:44 AM
なめられてるね
2:44 AM
💢
Avatar
あー、けど @koher さんのとはちょっと違うかな。
extension Array where Element == Optional まで書いて、型パラメータが書けなくて固まった・・・
Avatar
それはありましたね。それ書きたい・・・。
Avatar
omochimetaru 5/15/2017 2:48 AM
なるほど。
2:48 AM
やはりパラメータ付きextensionが要るのか。
Avatar
@norio_nomura さんの workaround 今回のに適用すると、 protocol HasElement { associatedtype Element } extension Array : HasElement {} struct Hoge<T> { } extension Hoge where T: HasElement { func fuga() -> T.Element { // 通る fatalError() } } (edited)
2:49 AM
extension<T> Array where Element == T? { var someValues: [T] { var result = [T]() for opt in self { if let value = opt { result.append(value) } } return result } }
2:49 AM
そのものずばり、マニフェストで提示されてる
Avatar
おお、そうなんだ。
Avatar
omochimetaru 5/15/2017 2:50 AM
Parameterized Extension と名付けられているようだ
Avatar
norio_nomura 5/15/2017 2:51 AM
よく覚えてるなあw
Avatar
関連して(ないような気もするけど)↓の動向が気になってる。 extension Array where Element == Int { ... }extension Array<Int> { ... } のように書けるようにするのには何か技術的な難しさがあるの?って質問(ちょっとニュアンス違うけど)。 https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170508/036599.html (edited)
Avatar
その件、ソース確認したんですが、無さそうです。純粋に syntax だけの制限だと思います。 concrete type extension が許可されてなかったから。
Avatar
なるほど。歴史的な経緯でこうなっているんですね。
Avatar
omochimetaru 5/15/2017 7:57 AM
--- Installing swift --- + env DESTDIR=/Users/omochi/work/swift-install/ /usr/local/bin/cmake --build /Users/omochi/work/swift-source/build/build-dir/swift-macosx-x86_64 -- install ninja: error: unknown target 'install', did you mean 'test/all'? utils/build-script: fatal error: command terminated with a non-zero exit status 1, aborting
7:57 AM
朝開始したやつさっきエラーで終わってた
7:57 AM
4.0branchのCI見てみよう
Avatar
@hiragram structのGenericsは見えないけどprotocolのassociatedtypeは見えるから
8:09 AM
例えばこういうコードなら通る struct Hoge<T> { let value: T } extension Hoge where T: BidirectionalCollection { func fuga() -> T.Iterator.Element { return value.first! } } Hoge(value: [1, 2, 3]).fuga() // 1
8:10 AM
って話が上の方にあった
8:10 AM
TをArrayっぽく任意のSequenceからinitしたい、みたいな感じだと
8:11 AM
Arrayのinitは、RangeReplaceableCollectionの実装だから
8:12 AM
extension Hoge where T: RangeReplaceableCollection { }と書いておけば、その中でT.initが使えるようになる
8:14 AM
BidirectionalCollectionはよく使うんだけどなんだったかな、lastが欲しいので使ってた気がする。
Avatar
omochimetaru 5/15/2017 8:20 AM
あ〜いけたかんじがする
8:21 AM
-- が 重要なのか
8:21 AM
$utils/build-script <options A> -- <options B> こうなってて、Aはbuild-scriptのやつ、 Bはbuild-script-implのやつか?
8:22 AM
--- Installing swift --- + env DESTDIR=/Users/omochi/work/swift-install/ /usr/local/bin/cmake --build /Users/omochi/work/swift-source/build/build-dir/swift-macosx-x86_64 -- install ninja: error: unknown target 'install', did you mean 'test/all'? utils/build-script: fatal error: command terminated with a non-zero exit status 1, aborting だめだw
Avatar
omochimetaru 5/15/2017 8:43 AM
あ〜 --reconfigureつけたらビルドしなおしになってしまった 終わり
8:48 AM
あれ、でもなんか中途半端に xctoolchain生成されてるな
Avatar
norio_nomura 5/15/2017 9:03 AM
build-script へ渡すオプションの組み合わせはプリセットとして swift/utils/build-presets.ini の中に記述されています。例えば OSS - Swift Package - OS X (master) で使われている buildbot_osx_package プリセットはこれ。 https://github.com/apple/swift/blob/master/utils/build-presets.ini#L955 (edited)
swift - The Swift Programming Language
Avatar
omochimetaru 5/15/2017 9:04 AM
あーなるほど
9:05 AM
ログの /Users/buildnode/jenkins/workspace/oss-swift-4.0-package-osx/swift/utils/build-script: note: using preset 'buildbot_osx_package', which expands to
9:05 AM
ここで、presetから実引数への展開結果が表示されてるので、展開結果のパラメータを1個ずつ見て移してました (edited)
Avatar
norio_nomura 5/15/2017 9:05 AM
swift/utils/build-presets.ini の代わりに自分で用意したものも --preset-file=… で使えます。 (edited)
9:11 AM
SourceKit for Linuxでのビルドにカスタマイズしたものを作って使ってました。 https://github.com/norio-nomura/swift-dev/blob/sourcekit-linux/build-presets-for-sourcekit-linux.ini
swift-dev - Managing Swift Repositories
9:13 AM
まあ、そんな諸々よりも --dry-run を使った方が早いかもしれませんが。
Avatar
omochimetaru 5/15/2017 9:31 AM
なるほど
Avatar
A brief overview of the complex topic of memory ownership revisions currently underway.
Swift Ownership Manifesto TL;DR
Avatar
omochimetaru 5/16/2017 1:35 AM
@rintaro ありがとうございます。
1:36 AM
昨日の19:30に発火したビルドが今みたらまだ終わってなかった
1:37 AM
preset自作していろいろ削らないと無理だなあ
Avatar
omochimetaru 5/16/2017 1:59 AM
CIで回ってるpresetを下地にオリジナルpresetでもろもろskipしてリトライ
Avatar
norio_nomura 5/16/2017 2:32 AM
次のSwift 4.0 DEVELOPMENT SNAPSHOTとどちらが早いか
Avatar
omochimetaru 5/16/2017 2:33 AM
既に過去のチェックアウトでやってるんで抜かされてるっていう・・・
2:33 AM
最終的にはまだプルリク段階の作業とかを試したいからやってます
Avatar
norio_nomura 5/16/2017 2:35 AM
ああ、ならばSmote Testとかで走るCIをやった方が良い気も。
Avatar
omochimetaru 5/16/2017 2:36 AM
PRのときになんかsmoke testって言葉出てきますね 何なのか知らないですが
Avatar
norio_nomura 5/16/2017 2:42 AM
テスト最低限でインクリメンタルなビルド時間が短いやつだと思ってます。
2:45 AM
どの部分へPR出すかによっても違うから、最終成果物を作成する方法を手元で再現しておくのは大事だよね
Avatar
omochimetaru 5/16/2017 2:46 AM
ですねえ
2:50 AM
というか、ビルド周りの情報もっとたくさんあるのかと思ってました
Avatar
norio_nomura 5/16/2017 2:54 AM
わからなかったらCIみろ、って感じですね。
Avatar
omochimetaru 5/16/2017 2:54 AM
昨日見てみて一個わからなかったのが
2:54 AM
CI summaryには変数式のスクリプトが書いてあるけど
2:54 AM
リポジトリを取ってきたり、一番最初のスクリプトを叩く行の内容とかが
2:54 AM
どこに定義されてるのかわからなかったです
2:55 AM
TravisCIとかならリポジトリの中にymlファイルが有るけど
2:55 AM
Jenkinsの側にメタデータとして書いてある感じがしてて、それを見る方法がわからなかった (edited)
2:56 AM
[oss-swift-4.0-package-osx] $ /bin/bash -e /var/folders/_8/79jmzf2142z2xydc_01btlx00000gn/T/hudson5232063434834374318.sh /Users/buildnode/jenkins/workspace/oss-swift-4.0-package-osx/swift/utils/build-script: note: using preset
2:56 AM
CIログの一番最初の、この、 hudson5232063434834374318.sh このシェルスクリプトの中身。
2:57 AM
swift/utils/build-script を叩くスクリプトだと思うけど、そのオプションとか、その前に環境変数をセットするとか、そういう作用がこのログに無い
Avatar
norio_nomura 5/16/2017 2:59 AM
ないですね。その辺りは非公開にしておかないとまずい部分もあるのだと想像。
Avatar
omochimetaru 5/16/2017 3:00 AM
なるほど・・・
3:00 AM
Travisしか触ったこと無かったので
3:00 AM
違和感がありました
3:01 AM
何か一個でも不可視の部分があるとそこの影響で何が起きるか計り知れないのでモヤモヤします
Avatar
norio_nomura 5/16/2017 3:05 AM
macOSのCIビルドはサードパーティーへの依存がほぼ無いので、それほど心配する必要はないと思います。
Avatar
norio_nomura 5/16/2017 3:07 AM
ぬ、コメント見えない
Avatar
omochimetaru 5/16/2017 3:07 AM
あら
3:07 AM
なるほど、これはまだ下書き状態なのか。
3:07 AM
すいません、使い方がわかっていなかった。
Avatar
norio_nomura 5/16/2017 3:12 AM
お手数おかけしました。
Avatar
norio_nomura 5/16/2017 3:35 AM
swift-4.0-DEVELOPMENT-SNAPSHOT-2017-05-15-a 来てた
Avatar
enumstructに変更してて気づいたんですがstaticstored property.hogehogeだけでアクセスできるんですね。 知らなかった。
Avatar
UIColorの.redとかでも使われてますよね
Avatar
static funcも返り値がSelfなら.fugafuga()で呼べます
Avatar
まだ知らないことがたくさんあるらしい。
Avatar
返り値Selfなら型を省略できるけど
Avatar
switch color { case .red: ... は出来ないという罠。
Avatar
代入先の型がprotocolだとできないことが結構ある (edited)
Avatar
まあそれは網羅できないし。
Avatar
RxでflatMap { .empty() }とか無理だったような(いけたっけ?
4:39 AM
代入先の型が具体的で、返り値がSelfの場合に限り、型の宣言を省略できる、かな。
Avatar
norio_nomura 5/16/2017 4:42 AM
.init(…) とかもよく使う。
Avatar
.init使いますね、そしてタプルが使えなくてFoooooってなる
Avatar
norio_nomura 5/16/2017 5:18 AM
コンパイラによる実装の自動生成ブーム的な。 we propose that a type synthesize conformance to Equatable/Hashable if all of its members are Equatable/Hashable https://github.com/apple/swift-evolution/pull/706
Avatar
↑これほしいようなほしくないような・・・。
5:23 AM
Users must opt-in to automatic synthesis by declaring their type as Equatable or Hashable without implementing any of their requirements.
5:24 AM
ああ、 Codable と同じように宣言は必須なのか。実装が自動挿入されるだけで。それならいいかも。
5:26 AM
自動生成、便利だけど判断ミスってやりすぎると取り返しのつかないものを入れてしまいそう。 Codable, Equatable, Hashable みたいな枯れた定型パターンならいいかもだけど。
5:26 AM
どうせなら public なイニシャライザの自動生成もほしい。
5:28 AM
↓こんなの。 public struct Foo { public var bar: Bar public var baz: Baz public var qux: Qux public init {} // 全プロパティを使って自動生成 }
Avatar
norio_nomura 5/16/2017 5:35 AM
CodableなクラスのサブクラスのCodable実装自動生成がうまくいっていないので、実装自動生成関連はまだ色々と修正が必要そう。
Avatar
omochimetaru 5/16/2017 5:54 AM
structならもうあると思うけど internal だから駄目って事ですか?
Avatar
そうです。
Avatar
omochimetaru 5/16/2017 5:59 AM
なるほど。
Avatar
swift-corelibs-foundationのドキュメントにはXcodeでビルドできると書いてあるけど、ci.swift.orgでXcodeによるビルドがテストされていないから、ビルドできない状態になっててもおかしく無いのかな。
Avatar
ドキュメントのメンテって難しいですね・・・
Avatar
なんか今日もいちにちかけたビルドが終盤のインストールでarmv7バイナリが無いとかでこけた
10:18 AM
iosのスキップした状態でパッケージさせるの無理そうなので
10:19 AM
自宅マシンをビルドサーバー化するところから出直す
Avatar
swift-corelibs-foundation 最新スナップショットtoolchainでもコケますが、 Xcode で Other Swift Flags に -swift-version 3 追加したら通りました。
👍 1
Avatar
そうか、Swift 4のプロトコルを使ってる==-swift-version 4 では無いってことか。
Avatar
SwiftFoundation, SwiftXCTest, TestFoundationに -swift-version 3 をつけていけました。ありがとうございます。
Avatar
@omochimetaru iOSテストのスキップではなくビルドもスキップしてたのですか?
Avatar
はい。
11:13 AM
macだけ動けばいいので
Avatar
なるほど。
Avatar
あるものだけかき集めてパッケージするような挙動に期待してた
Avatar
この間ちらっと話題に上がった、クロージャを引数に取る場合にデフォルトで何もさせたくない場合にどうするかというの
2:54 PM
public func nop<T>(_ v: T) {} こういうの作って
2:54 PM
public func doOptional(_ closure: ((Int) -> ())? = nil) { closure?(1) } public func doEmpty(_ closure: @escaping ((Int) -> ()) = nop) { closure(1) } 計測してみたけど、普通にOptionalのほうが速かったw (edited)
2:57 PM
2:57 PM
Optimizeしても似た比率の結果。引数に渡す時点でコピーが走るとか、冷静に考えたらそりゃそうかという感じ
2:57 PM
無になってはくれなかった。
Avatar
なるほど
Avatar
Kotlift is the first source-to-source language transpiler from Kotlin to Swift
Avatar
Data class サポートしてないとかキツイですね…。
Avatar
omochimetaru 5/18/2017 1:33 AM
@tarunon nonescapingにしないの?
1:33 AM
ああ逆か
1:33 AM
ん?
1:33 AM
いややっぱ変だな
Avatar
escapingの有無、引数に渡すものをvoid、GenericsではなくAny、全て試したが
Avatar
omochimetaru 5/18/2017 1:34 AM
うん
Avatar
全てのケースでOptionalの方がはやい。
Avatar
omochimetaru 5/18/2017 1:34 AM
え〜 non-escaping ならインライン化されるから無になると思ったが・・・
Avatar
引数に渡す部分が無にならない気がする
1:35 AM
コピーやAnyへのラップが発生することが、オーバーヘッドとして露出していて
1:35 AM
それらはnilチェックより高コストだった
Avatar
omochimetaru 5/18/2017 1:36 AM
あ、nop関数は別途名前を定義してるのか
Avatar
{ _ in }こいつだと
1:37 AM
Optionalと同じぐらいのスピードになったが、明確に速いと言えるほどの差は無かった気がする、Voidでは。Intだとどうだったかな、記憶があやふやだ (edited)
Avatar
omochimetaru 5/18/2017 1:38 AM
最適化は有効化した?
Avatar
やってるぞ
Avatar
omochimetaru 5/18/2017 1:38 AM
なるほど。
Avatar
上のキャプは最適化は無だけど、最適化しても同程度の比率なのは確認した。
1:40 AM
まあ考えてみれば、関数を引数に直接渡してるわけではなく、クロージャにラップして渡してるはずだし
1:41 AM
クロージャが無かどうかなんて、コンパイル時に判断できないから無になるわけがなかった
Avatar
関数を渡すときってラップされるんですか?
Avatar
omochimetaru 5/18/2017 1:52 AM
@koher Swiftのクロージャ表現にはバイナリが3種類あって
1:52 AM
環境キャプチャ(func in func)したりメソッドでない場合は
1:53 AM
ネイティブ関数ポインタになるはずですが (64bit)
1:53 AM
この例だと型パラメータがついてるので
1:53 AM
それに当てはまるか謎
Avatar
func nop(_ v: Any){}でも、計測結果に差は無かった。期待される関数の型と、渡される関数の型が違う場合は全てクロージャにラップされてるのでは?と言う気がしている
Avatar
omochimetaru 5/18/2017 1:55 AM
その場合はthunkが作られるはずだねえ
Avatar
両方Voidにして、func nop(_ v: Void){}ならOptionalに追いついた気がする
Avatar
omochimetaru 5/18/2017 1:55 AM
クロージャのアップキャストを表現するために包むだけのやつ
Avatar
同じパッケージだとジェネリックでもspecializeされないの?
Avatar
thunkになった段階で無かどうかコンパイルタイムに判断できない気がする
Avatar
omochimetaru 5/18/2017 1:58 AM
thunkのコード自体はコンパイラから静的に見えるからインライン展開のインライン展開を期待してた
1:58 AM
今度自分でもいろいろなパターンで実験してみる
Avatar
nop<T>が最適化されないと、現実的なシチュエーションでは使いづらい感
Avatar
omochimetaru 5/18/2017 1:59 AM
デフォルト引数の部分には = { in } って書けないんだっけ?
Avatar
書けるけど、Optionalと等速なので
2:00 AM
採用する価値がない気がする
2:01 AM
func nop<T>(_ v: T){} func foo(_ closure: (Int)->()=nop) {...} ↑undefined<T>以来のヒットだと思ったけど、残念w
Avatar
norio_nomura 5/18/2017 2:11 AM
パラメータ Void は warning が出るようになった。 warning: when calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'? public typealias XCPredicateExpectationHandler = (Void) -> (Bool) ^~~~~~ ()
Avatar
omochimetaru 5/18/2017 2:12 AM
あら・・・・・
Avatar
var fuga: Bool! let a: Int = fuga ? 1 : 2 コンパイラがセグフォでしぬ
Avatar
omochimetaru 5/18/2017 5:44 AM
ほんとだw
Avatar
var fuga: Bool! = true (or false) でもしぬ
Avatar
omochimetaru 5/18/2017 5:45 AM
それはへいきだった
Avatar
アレ?
5:45 AM
var fuga: Bool! = true let a: Int = fuga ? 1 : 2 俺はこれのつもりで言ってたけどあってる?
Avatar
omochimetaru 5/18/2017 5:46 AM
いや
5:46 AM
2行目は消した
Avatar
(fuga==true)?1:2
5:46 AM
Avatar
なるほど
5:46 AM
そうそう
Avatar
というかBool!が出現するのはどうなんだ
Avatar
omochimetaru 5/18/2017 5:46 AM
www
Avatar
それはまあ
5:46 AM
そう。
Avatar
IUOを見ると突っ込まずには居られない
Avatar
絶対来ると思ったよ
5:47 AM
var fuga: Bool! let a: Int = (fuga ?? true) ? 1 : 2 IUOやめろは一旦おいておいてこれはコンパイル通るからBool!と三項演算子が良くないっぽ
Avatar
なんでnilがtrueになるんや!!
Avatar
それはまあ
5:48 AM
そう
Avatar
そういう意味は無いからw
Avatar
let だとだいじょぶ
Avatar
omochimetaru 5/18/2017 5:48 AM
報告しなきゃ
Avatar
Avatar
omochimetaru 5/18/2017 5:49 AM
多分誰も今までBool!を?:で使ったことがないんだよ
Avatar
@rintaro これであってますか? let fuga: Bool! let a: Int = fuga ? 1 : 2
5:49 AM
通らん
5:50 AM
let fuga: Bool! = true let a: Int = fuga ? 1 : 2 これは通った。
Avatar
明示的に初期化しないとだめですね。
5:51 AM
l-value expression does not have l-value access kind set エラーとしてはこれなので、 l-value 性を保ったまま ?: に突っ込むと失敗する感じ。
Avatar
IUOをアンラップすると通る? var fuga: Bool! = true let a: Int = fuga! ? 1 : 2
Avatar
明示的にアンラップすればそれはただのBool or dieだし通るの納得
5:52 AM
@omochimetaru こういうのって報告するとしたらどこにどう報告するもんなんすか
Avatar
omochimetaru 5/18/2017 5:59 AM
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
JIRAか
Avatar
norio_nomura 5/18/2017 9:13 AM
whats-new-in-swift-4 - An Xcode playground showing off the new features in Swift 4.0.
Avatar
one-sided-rangeはprefix/postfixなので i+1..<j-1に対して(i+1)...とか..<(j-1)とか括弧つけないとだめですよね。 これも一掃できたら綺麗だと思うんですが。
Avatar
omochimetaru 5/19/2017 7:21 AM
class Animal { // コンパイルOK func aa() -> Self { return self } static func bb() -> Self { // コンパイルを通せるコードが見当たらない } }
7:21 AM
プロトコル定義の中 ではなく 、実際のクラスの中で Self って書くと、 self の型 を意味するようなんですが
7:22 AM
こっちの具体的な型の中での Self は、フィールドや引数やクロージャ型に混ぜて使うと怒られて、この、インスタンスメソッドの返り値と、スタティックメソッドの返り値の2箇所にしか書けなくて
7:22 AM
そして、インスタンスメソッドの場合は、 self でしか満たせないように思えるんだけど
7:22 AM
スタティックメソッドの場合はどうすれば満たせるんだろう? 絶対に満たせないなら、 インスタンスメソッドの返り値部分だけ に使える、って仕様で良いと思う。
7:23 AM
'Self' is only available in a protocol or as the result of a method in a class;
このようなエラーメッセージが出るけど、 result of a instance method で良いと思うんですよね。
Avatar
@omochimetaru class Animal { static func cast<T: Animal>(animal: Animal) -> T { guard let animal = animal as? T else { fatalError() } return animal } static func bb() -> Self { return cast(animal: Animal()) } }
7:24 AM
力技で通したよ
7:24 AM
Himotokiを使ってると似たようなパターンに遭遇することがあって、こんな感じでゴリ押しして押し通った記憶がある
Avatar
omochimetaru 5/19/2017 7:25 AM
これって Animal() as! Self って書いてるのと何が違う?まあこれは書いても怒られたんだけど、意味的には一緒?
Avatar
一緒ですね
Avatar
omochimetaru 5/19/2017 7:25 AM
ななるほど
Avatar
static func bb() -> Self { return .init() } とか?
Avatar
んーコンパイルしたあとのコードは違うかも
7:26 AM
@rintaro require initにすればいけますね
Avatar
omochimetaru 5/19/2017 7:26 AM
あ〜〜〜
7:27 AM
うおおとおった
7:27 AM
class Animal { static func bb() -> Self { return .init() } }
Avatar
initがrequireじゃなくても通るの
7:27 AM
通ったとしても、実行時に死ぬ気がする
Avatar
finalクラスならrequireじゃなくてもいけそう
Avatar
omochimetaru 5/19/2017 7:28 AM
class Animal { init(x: Int) { } static func bb() -> Self { return .init(x: 3) } }
7:28 AM
これもいけるぞ?????
Avatar
requireじゃないと、サブクラスでbb呼んだ時に確実に死ぬ
7:29 AM
ってことはそれはコンパイラのバグっぽい
Avatar
omochimetaru 5/19/2017 7:29 AM
やってみますね
Avatar
多分、本物のぬるぽを見ることはなくって、initが存在しないで死ぬ気がするけど
Avatar
omochimetaru 5/19/2017 7:31 AM
class Animal { init(x: Int) { } static func bb() -> Self { return .init(x: 3) } } class Cat : Animal { } func main() { print(Cat.bb()) } main() [omochi@omochi-MB stt]$ swift a.swift a.Animal
Avatar
class Animal { // コンパイルOK func aa() -> Self { return self } class func bb() -> Self { return .init() } } class Dog : Animal { init(x: Int) { super.init() } func bowow() {} } let a: Dog = Dog.bb() a.bowow() 最後の行まで死なない。
Avatar
omochimetaru 5/19/2017 7:31 AM
Cat.bbよんだらAnimalでてきた
Avatar
えーっと
7:31 AM
Catにフィールド1個足して、別のinitを定義しないと
7:31 AM
マジカ
7:31 AM
最後の行まで死なない…
Avatar
omochimetaru 5/19/2017 7:32 AM
a
7:32 AM
たるのんのいうとおりだ
7:32 AM
バグだ
7:32 AM
クラッシュした
7:32 AM
class Animal { init(x: Int) { } static func bb() -> Self { return .init(x: 3) } } class Cat : Animal { var name: String = "cat dayo" } func useCat(cat: Cat) { print(cat.name) } func main() { useCat(cat: Cat.bb()) } main()
7:32 AM
useCatは静的にCatの式になってて、cat.nameでプロパティアクセスさせてるけど
7:32 AM
Cat.bb()がCatを返すという静的な扱いなのに、実際にはAnimalを返してる関係で吹っ飛ぶ
7:34 AM
@rintaro このようにちょっと追記したら吹っ飛びました class Dog : Animal { var name: String = "I am pochi" init(x: Int) { super.init() } func bowow() { print(name) } } (edited)
Avatar
「最後の行まで死なない」は、「最後の行で死ぬ」の意でした。
Avatar
omochimetaru 5/19/2017 7:35 AM
あ、なるほど。
Avatar
Doginit() 持ってないから、死ぬなら一つ前の行で死なないと。
Avatar
omochimetaru 5/19/2017 7:36 AM
initメソッド、というかイニシャライザは、理論的にはSelfを返す式なんですね
7:37 AM
だから、 他の static func ccc() -> Self のような、Self を返すstatic methodを呼ぶのと解釈的には同じかな
7:38 AM
まあそれだと堂々巡りになっちゃうので、ほんとうの意味で Self を作れる init が特別な存在か
7:39 AM
これも Dog(type: "cat") 呼べちゃうっていう問題がきつい (edited)
Avatar
omochimetaru 5/19/2017 7:39 AM
catでinit定義してもうまくいかねえな
7:39 AM
required initにしたら全部うまくいった。
Avatar
そう、required initはちゃんと動く
Avatar
omochimetaru 5/19/2017 7:40 AM
required initは class func 的なものになってそうだなあ
7:40 AM
@rintaro 絵文字w
7:41 AM
え、これなにがおこってんの・・・
7:41 AM
init(factory: () -> Self) { self = factory() } まずこれがヤバ
Avatar
Swift でクラスクラスタを無理矢理実現するの。
Avatar
omochimetaru 5/19/2017 7:42 AM
swiftでもselfって差し替えられたの・・・・
Avatar
protocol の mutating funcinit ではいけちゃいます。
Avatar
protocol extensionにinitの実装書けるのと、その中ではselfの差し替えができてしまう、という
7:44 AM
ひどいw
7:44 AM
あれ?
7:44 AM
これは良いことを思いついてしまった
Avatar
omochimetaru 5/19/2017 7:44 AM
これは任意のクラスのインスタンスを差し替えられる・・・?
7:45 AM
mock的な何かに・・・?
Avatar
StoryboardとNib
Avatar
omochimetaru 5/19/2017 7:46 AM
えっ、これおかしすぎないか・・?いいのか??
Avatar
ww
Avatar
https://gist.github.com/rintaro/1668e46bc969c5f991079dd5bf530dd1 こういうユーザ側で予期しない挙動になるので、使いすぎ注意。
Avatar
やべぇ
Avatar
omochimetaru 5/19/2017 7:48 AM
mutating func ってクラスでは使えないと思ったけど
7:48 AM
protoocl の mutating経由だとできるのか・・・
Avatar
Nib, Storyboardのinitに悪用できないか真面目に考えよう
Avatar
omochimetaru 5/19/2017 7:50 AM
あーじゃあextension経由でmutatingメソッドをvarに対して呼んでる時
7:50 AM
ちゃんとクラスでもvarのselfそれ自体の差し替えが
7:50 AM
発行されてるのか
Avatar
ですね。 mutating funcself のセマンティクスは inout と同じです。
Avatar
omochimetaru 5/19/2017 7:51 AM
ref1.reset() この行が mutating の呼び出しだから var の値の変更をする可能性があって、それでObjectIdentifierが変わると
7:51 AM
ああ、そうですね。
Avatar
これすごいな
Avatar
omochimetaru 5/19/2017 7:52 AM
ちょうどownership周りの文書でもそこが整理されてた。
7:53 AM
でもそれならclassでもmutating func 定義できて良い気がする 、それができないのに現状でこれができるのはおかしい感じが・・・
7:55 AM
@rintaro ていうかこれどこで気がついたんですか?w
Avatar
stdlib のソース見てたら、 https://github.com/apple/swift/blob/master/stdlib/public/core/Integers.swift.gyb#L1141-L1143 protocol extension で self = みたいなのがあって、じゃあ出来るじゃん的なw
swift - The Swift Programming Language
Avatar
omochimetaru 5/19/2017 7:59 AM
なるほどw
8:00 AM
SignedNumericってだいたい継承先はstructな気がするけど、別にプロトコルなんだからもしクラスだったら?・・・って流れか
8:01 AM
そっかー selfそれ自体がinoutセマンティクスってそういうことかあ・・・
Avatar
悪用しようと思ったけどletとの共存は無理っぽいし嬉しさはそんなに増えなかった
8:01 AM
それなら黒魔術使ってまでinitに固執することもないなという感
Avatar
omochimetaru 5/19/2017 8:01 AM
ちょうどownershipでプロトコル: struct / class 周りで理論的な整合がよくわからなかったけど、こうやって整理されるんだなあ
8:02 AM
あら。
8:02 AM
また謎のバグを見つけるオチかと思ってたけど微妙だったか
Avatar
謎のバグw
8:03 AM
super.initを呼ぶか、convenience initにするしか無いのだけど、そうすると、letへの代入の順番の制約か、そもそもそれ自体ができない、ということになるので
Avatar
そもそもsuper.init呼ぶの無理だった
8:10 AM
どうやってもconvenience initじゃないといけないですね
Avatar
norio_nomura 5/20/2017 5:11 AM
swift-4.0-DEVELOPMENT-SNAPSHOT-2017-05-17-aSequence.Element が追加されて、Sequence準拠したenumcaseとして定義されているElementとぶつかったのだけど、これって-swift-version 3で回避できるようになる類の変更なのだろうか? https://bugs.swift.org/browse/SR-4951 (edited)
Avatar
-swift-version で回避できるとは思えないですねぇ。 -swift-version 毎のstdlibを用意するくらいしないと回避できない気がします。 (edited)
Avatar
norio_nomura 5/20/2017 7:44 AM
やはりそうですよね…
Avatar
norio_nomura 5/22/2017 3:48 AM
現状、#if swift(>=3.2)って書くと、Swift 4で-swift-version 3を指定したビルドと、Swift 3.1.1ビルドを区別できるぽい。
3:50 AM
WWDCでXcode 9にswift-3.0-branchからのSwift 3.2とSwift 4の両方が入ってくるとしたら、これも使えなくなるのかな。 (edited)
3:54 AM
Swift 4の-swift-version 3とSwift 3.xを全く同じコードで対応ってのは、どうしても無理な場合が出てくるので、区別できるようにしてほしいなあ。
Avatar
let a = [""].map { $0 }.prefix(3) let b = [""].prefix(3).map { $0 } // Ambiguous use of 'prefix' [String]#prefixArraySlice<Sequence>を返すものとAnySequence<String> を返すものがあるんですが bのみambiguousになってaArraySlice<String>に寄るのは何でですかね? 片方に寄せることが決まってるならbもやってくれても良いんじゃないかと思うんですが。 (edited)
Avatar
AnySequenceのほうのprefixの定義に飛べなくて調べられない……
Avatar
1> let a = [""].map { $0 }.prefix(3) a: ArraySlice<String> = 1 value { [0] = "" } 2> let b = [""].prefix(3).map { $0 } error: repl.swift:2:9: error: ambiguous use of 'prefix' let b = [""].prefix(3).map { $0 } ^ 2> let b = [""].prefix(3) b: ArraySlice<String> = 1 value { [0] = "" } 3> b.map { $0 } $R0: [String] = 1 value { [0] = "" }
7:18 AM
@t.ae 1は間に map が入ってその戻り値は [String] しかないから型を決定しやすそう。
Avatar
ArraySliceによるのはAnySequenceがより広範な定義になってるからとかですかね?(まだ定義部が分かってない) しやすい、しにくいというのならambiguous~とでてる時点で2つに絞り込めているはずなので、 それをlet b = [""].prefix(3)だと判断できてるのにmapがついただけでambiguousになるのがいまいち解せないです。
Avatar
2 は [""]  が [String] とも決定できてないかも?
Avatar
そこ一時変数置いたのも試してるんですよね。
Avatar
ん? 3 と 4 に分割したら通ったよ??
Avatar
いや
7:26 AM
let a: ["String"] = [""] a.prefix(3).map { $0 } が通らないという話です。
Avatar
なるほど
7:26 AM
mapArraySlice にも AnySequence にもあるから、後ろに map が続くという条件の元では ArraySlice 優先が消えて AnySequence と同格になってるのかも。
Avatar
mapのほうから型推論しようとしてるならそうとも考えられそうですね。
Avatar
norio_nomura 5/23/2017 7:52 AM
extension Collection { public func prefix(_ maxLength: Int) -> SubSequence { } } extension Sequence where SubSequence : Sequence, SubSequence.Iterator.Element == Iterator.Element, SubSequence.SubSequence == SubSequence { public func prefix(_ maxLength: Int) -> AnySequence<Iterator.Element> { } } extension Collection { public func map<T>( _ transform: (Iterator.Element) throws -> T ) rethrows -> [T] { } } extension Sequence { public func map<T>( _ transform: (Iterator.Element) throws -> T ) rethrows -> [T] { } } (edited)
7:53 AM
式の末端から型推測しようとしてるからぽい。
Avatar
あー
Avatar
norio_nomura 5/23/2017 7:54 AM
where の制限が多いかどうか?が、末端でしか評価されていないのかな?
Avatar
[""]ArraySlice<String> の可能性を考慮してるのか。
7:55 AM
[""][String] だと AnySequence の方の prefix は条件に当てはまらないけど
Avatar
なんとなく双方向で型推論してくれてるんだと思ってたんですがそうでもないんですね
Avatar
いや、双方向で推論しても解決できないんじゃない?
Avatar
[""].prefix(3)ArraySliceになるのを解決できてるとするなら、ですね (edited)
Avatar
2> let b: ArraySlice<String> = [""] b: ArraySlice<String> = 1 value { [0] = "" } 3> b.prefix(3).map { $0 } error: repl.swift:3:1: error: ambiguous use of 'prefix' b.prefix(3).map { $0 } ^ 3> b.prefix(3) $R0: ArraySlice<String> = 1 value { [0] = "" }
7:58 AM
うーん
7:58 AM
たしかに最初の 3 でも決定できないか
7:59 AM
あれ?読み間違えてた
7:59 AM
SubSequence == Sequence じゃないのか
8:00 AM
↓って何のためにあるんだろう? extension Sequence where SubSequence : Sequence, SubSequence.Iterator.Element == Iterator.Element, SubSequence.SubSequence == SubSequence { public func prefix(_ maxLength: Int) -> AnySequence<Iterator.Element> { } }
Avatar
そもそもこのwhere句が何を期待しているのかも分かりにくいですね
8:03 AM
一見Subsequenceを更にイテレートするように見えるのですが
Avatar
SubSequence.SubSequence == SubSequence これが何のためかよくわかんないね。
Avatar
これはSubSequenceが自分自身と同じ型という意味だと思います
Avatar
それはわかるんですが、何を目的としているのかがいまいちわからず・・・。
Avatar
同上
Avatar
SubSequenceが自身の型なら、prefixは自明だから実装できるということでは
Avatar
omochimetaru 5/23/2017 8:06 AM
SubSequenceが自分自身とは違う型になるパターンがあるからでは?
Avatar
norio_nomura 5/23/2017 8:06 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
自動実装のためってことですかね
Avatar
SubSequenceが自身の型でないとprefixが実装できないですか?
Avatar
AnySequenceのinitの条件がそれなのでは
Avatar
ほんとだ
Avatar
なるほど。そうすると、もう一つ僕がよくわからないのは、戻り値を AnySequence とした prefix のオーバーロードがほしい理由ですね。 (edited)
Avatar
あー、んんー?
Avatar
この制約は AnySequenceinit が担保するから、 AnySequence がほしければ普通に AnySequence(foo.prefix(3)) とかでいい気が。
Avatar
extension Sequence where SubSequence : Sequence, SubSequence.Iterator.Element == Iterator.Element, SubSequence.SubSequence == SubSequence { public func prefix(_ maxLength: Int) -> AnySequence<Iterator.Element> { } } これもしかしてSubSequenceがAnySequenceであることを示唆してる気がしてきた(AnySequence.SubSequence==AnySequence) (edited)
Avatar
omochimetaru 5/23/2017 8:11 AM
そのExtension定義に飛ぶ方法誰か教えて
Avatar
SubSequenceがAnySequenceであることは、where句に書けないかな?
Avatar
そうですか? [String]だとSubsequence == ArraySlice<String>Subsequence.Subsequence == ArraySlice<String>だと思いますけど
Avatar
いや、今 ArrayArraySlice に対してこの prefix が候補であいまいだと言われてるので、
8:12 AM
普通に ArrayArraySlice でも当てはまると思います。
Avatar
omochimetaru 5/23/2017 8:12 AM
extension Sequence where Self.SubSequence : Sequence, Self.SubSequence.SubSequence == Self.SubSequence, Self.SubSequence.Iterator.Element == Self.Iterator.Element { これか
Avatar
ArraySliceSubSequenceArraySlice だから
Avatar
普遍的なTに対してSubSequence==ArraySlice<T>って書けるのかな
Avatar
ArraySlice の場合は T によらず SubSequenceArraySlice<T> ですよね?
Avatar
extension Sequence where Self.SubSequence == AnySequence<Self.Iterator.Element> { }
8:15 AM
これも出来るしなんだろう
Avatar
norio_nomura 5/23/2017 8:16 AM
当時はできなかったのでは。 (edited)
Avatar
ああ、そういうことか。そういう制約の代わりに書いてるんじゃないかってことですね。
Avatar
これ書けるようになったのって3以降か3.1以降な気がする、どっちだろ
8:17 AM
2で書けたかなー
Avatar
でもそれだと大分意味が変わっちゃてるなぁ。素直に読んだら、このオーバーロードで AnySequence でラップする手間を減らしてあげるよってことな気も。
Avatar
でも実装見る限りは、ラップしてあげますよというよりはデフォルト実装がある、というように見える
Avatar
便利だからそのデフォルト実装生やしてあげますよってことじゃないですか?
8:20 AM
prefix の結果を AnySequence で受け取りたいときもあるでしょう?オーバーロードを作っておいてあげますよ。」ってことかなぁと。
8:21 AM
その結果、類似した型を返す prefix が二つできて曖昧になってしまったんだったらひどい話・・・
Avatar
これSwiftの挙動を踏まえて考えると、SubSequence宣言しなかったらtypealias Sequence=AnySequence<Iterator.Element>に推論される気がする (edited)
8:23 AM
あーー
8:23 AM
されないか
Avatar
↓であいまいになっちゃうの流石に辛い気が。でもこの prefix をなくすより型推論の優先順位をしっかり決めて、↓の prefixArraySlice を返すようにできたらいいのかな。 [""].prefix(3).map { $0 }
Avatar
extension Sequence where SubSequence=AnySequence<Iterator.Element> これを書くとそうなる
8:23 AM
それを避けるためのワークアラウンドなのかしら
Avatar
norio_nomura 5/23/2017 8:24 AM
CollectionはSubSequenceを作れるsubscriptがあるけど、Sequenceには無いからAnySequenceなのでは。 (edited)
Avatar
@omochimetaru 単純に prefix だけだと ArraySlice を返す方が優先されてるけど、 map が後ろにつながることで、 ArraySlice を返す prefixAnySequence を返す prefix の優先順位が同格化されちゃってるんだと思います。 map につながりうるもの、みたいな。
8:26 AM
@omochimetaru map の後ろに prefix だったら map の時点で戻り値が [String] だから、 b.prefix(3) が解決できるのと同じなので問題なし。
8:27 AM
@norio_nomura デフォルト実装は AnySequence 版しか作れないから、ってことですか?
Avatar
norio_nomura 5/23/2017 8:27 AM
そそ。
Avatar
extensionでassoctypeを具体型で縛って具体型を返り値に持つfunctionのデフォルト実装を書くと
8:29 AM
暗黙のうちにassoctype自体がデフォルト型を持ってしまうバグ?があって
Avatar
うーん、でも結局 Sequence の具象型の側で↓は実装しないといけないですよね?デフォルト実装のうまみがあまりない気が・・・。 func prefix(_ maxLength: Int) -> Self.SubSequence
Avatar
それを避けるためなのでは?という邪推
Avatar
omochimetaru 5/23/2017 8:29 AM
ふーむ
Avatar
Sequecneの具象型でprefix定義しなくても良くないですか?
Avatar
extension Sequence where SubSequence==AnySequence<Self.Iterator.Element> { ... } // これと protocol Sequence { associatedtype SubSequence = AnySequence<Iterator.Element> // これは今できないけど、仮にできたとして、等価になる。 }
Avatar
@t.ae なんででしょう?
Avatar
https://github.com/t-ae/ndarray/blob/master/Sources/Sequence.swift 最近書いたのですけどこれだけでAnySequenceが返るprefixが使えて
ndarray - Float NDArray library accelerated with Accelerate Framework
8:33 AM
んーでもちがうな
Avatar
@t.ae Sequence 自体が↓を持ってるんじゃないの? func prefix(_ maxLength: Int) -> Self.SubSequence
Avatar
補完でそっちでないんでそれがAnySequenceので実装されてるのかと思ったんですがそもそもSubsequenceの型が違いますよね……
Avatar
これがそのまま動くのだとしたら、SubSequenceはAnySequenceだと推論されてると思う
Avatar
ああそうか、そうですね 完全に間違ってました
8:35 AM
Subsequenceを指定するかどうかで変わるのか
Avatar
はい。 Array なら SubSequenceArraySlice なので ArraySlice を返す prefix の実装が必要になります。
Avatar
この挙動を避けるために、まどろっこしい書き方してるのかなと思ったけど避けれてないならさっきの憶測は関係なさそう
8:36 AM
しかし、明示しなくてもassoctypeのデフォルト型の振る舞いが出現するのはバグっぽい
Avatar
norio_nomura 5/23/2017 8:37 AM
Sequence準拠にprefix実装なんて必要ないですよね。
Avatar
/// Returns a subsequence, up to the specified maximum length, containing /// the initial elements of the sequence. /// /// If the maximum length exceeds the number of elements in the sequence, /// the result contains all the elements in the sequence. /// /// let numbers = [1, 2, 3, 4, 5] /// print(numbers.prefix(2)) /// // Prints "[1, 2]" /// print(numbers.prefix(10)) /// // Prints "[1, 2, 3, 4, 5]" /// /// - Parameter maxLength: The maximum number of elements to return. /// `maxLength` must be greater than or equal to zero. /// - Returns: A subsequence starting at the beginning of this sequence /// with at most `maxLength` elements. public func prefix(_ maxLength: Int) -> Self.SubSequence
8:38 AM
ある
Avatar
norio_nomura 5/23/2017 8:39 AM
swift - The Swift Programming Language
Avatar
SubSequenceのデフォルト型としてAnySequenceが宣言されていないのに、デフォルト型として振る舞うのは変じゃないですか?
Avatar
SubSequence が定まらないからデフォルト実装できなくないですか?
8:40 AM
あー、そういうことか。
Avatar
norio_nomura 5/23/2017 8:40 AM
/// Conforming to the Sequence Protocol /// =================================== /// /// Making your own custom types conform to `Sequence` enables many useful /// operations, like `for`-`in` looping and the `contains` method, without /// much effort. To add `Sequence` conformance to your own custom type, add a /// `makeIterator()` method that returns an iterator. /// /// Alternatively, if your type can act as its own iterator, implementing the /// requirements of the `IteratorProtocol` protocol and declaring conformance /// to both `Sequence` and `IteratorProtocol` are sufficient.
Avatar
SubSequenceAnySequence だった場合に
Avatar
普遍的なSequenceのextensionにAnySequenceが生えてるなら
8:41 AM
宣言なしならそれが推論されるのはまあわかる
Avatar
デフォルト実装が不要になる?
Avatar
norio_nomura 5/23/2017 8:41 AM
/// Here's a definition of a `Countdown` sequence that serves as its own /// iterator. The `makeIterator()` method is provided as a default /// implementation. /// /// struct Countdown: Sequence, IteratorProtocol { /// var count: Int /// /// mutating func next() -> Int? { /// if count == 0 { /// return nil /// } else { /// defer { count -= 1 } /// return count /// } /// } /// } /// /// let threeToGo = Countdown(count: 3) /// for i in threeToGo { /// print(i) /// } /// // Prints "3" /// // Prints "2" /// // Prints "1"
Avatar
条件付きextensionに生えてるなら、鶏卵問題が発生しているので違和感が激しい
Avatar
なるほどー。 extension のデフォルト実装によって暗黙的に SubSequnceAnySequence で埋められるのか。
8:42 AM
それによって makeIterator さえ実装すればカスタム Sequence が作れると。
Avatar
普遍的なのに生えてるとしてもそこでSubsequenceは使えるのでAnySequenceなのはおかしいですよね?
Avatar
さっきのだとSequenceの条件があってはじめて、prefixが生えてませんか?
8:43 AM
protocol A { associatedtype B func hoge(arg: B) } class C: A { func hoge(arg: String) { } }
8:44 AM
条件なしなら、これが通る理由をそのまま適用できる
Avatar
鶏卵的ですが、 AnySequence はそれを満たすから SubSequenceAnySequence なら OK ってことじゃないですか?
Avatar
AnySequenceならそれを満たせるから、それで初めて、SubSequenceAnySequenceだと理解できるはずで、
8:45 AM
条件付きに関して言うとAnySequenceが無から湧いていてやばい
8:45 AM
えーっと
Avatar
普遍的に生えてるのが、SubSequenceが未指定だとそれを埋めるってことになるんですかね
Avatar
https://github.com/apple/swift-evolution/blob/master/proposals/0014-constrained-AnySequence.md これを読んだのですがよくわからなかかった。
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
なんか、今手元に100万円あったら将来的に1億円になることがわかっている株があるけど、未来の1億円から100万円借りてその株を買う的な気持ち悪さがある・・・。
Avatar
norio_nomura 5/23/2017 8:46 AM
struct Countdown: Sequence, IteratorProtocol { var count: Int mutating func next() -> Int? { if count == 0 { return nil } else { defer { count -= 1 } return count } } } let s = Countdown(count: 10).prefix(3) // AnySequence<Int>
Avatar
omochimetaru 5/23/2017 8:46 AM
みんなの言ってる事がよくわからない
Avatar
protocol A { associatedtype B func hoge(arg: B) } extension A where B == Void { func hoge(arg: Void) { // こっちはB無しでVoidが推論されるが } } extension A where B == Void { func hoge(arg: B) { // こっちはB無しだとコンパイルFail } } こういう挙動もあって、僕の中ではバグ説が非常に高い
8:47 AM
で、宣言なしAnySequenceの挙動は、どうも、これに準拠している気がしていて
Avatar
@omochimetaru SubSequenceAnySequence だったらさっきの extension の条件を満たせて prefix を実装したことになるんだけど、そのためには prefix の戻り値から SubSequenceAnySequence であることを推測しないといけない気がしてる。
Avatar
omochimetaru 5/23/2017 8:48 AM
ふむふむ
8:50 AM
func f<X: Sequence>(x: X) { print(x.prefix(3)) }
8:50 AM
単純にこれがコンパイルできるのは
Avatar
それは単に Sequenceprefix があるからでは。
Avatar
omochimetaru 5/23/2017 8:51 AM
protocol定義本体に、 AnySequenceを返るfuncがあるからで
8:51 AM
問題は、
8:51 AM
事前定義済みのその実装としては
8:51 AM
extension Sequence where Self.SubSequence : Sequence, Self.SubSequence.SubSequence == Self.SubSequence, Self.SubSequence.Iterator.Element == Self.Iterator.Element {
8:51 AM
っていう条件付きのやつしかないのに
8:52 AM
ユーザー定義Sequenceについて、これが呼ばれるようになる理由が謎ってこと? (edited)
Avatar
いや
8:52 AM
protocol定義本体はSubSequenceでしか無いんじゃない、別にそれでもprintは通る
Avatar
omochimetaru 5/23/2017 8:53 AM
ああそうか。本体に定義されてるのはSubSeuqneceが返るやつか。
Avatar
protocol定義本体に、 AnySequenceを返るfuncがあるからで
それはなくない?本体にあるのは↓じゃない? func prefix(_ maxLength: Int) -> Self.SubSequence
Avatar
条件付きextension以下にAnySequenceが書かれているが、一体何を材料に、そのSubSequenceをAnySeuqenceと断定できるのか、という
Avatar
ああ、入れ違いに。
Avatar
omochimetaru 5/23/2017 8:53 AM
えーっと、そうすると何が不思議なんですっけ?
8:54 AM
protocolを満たす時にSubSequenceがAnySequenceで埋まればそのextensionのバージョンが呼べるってだけじゃないのか
Avatar
なので、 prefix の実装を持ってくるためには
Avatar
omochimetaru 5/23/2017 8:54 AM
AnySequenceで埋まって無さそうなのに、そのバージョンが呼ばれてる、事例が観察できたの?
Avatar
SubSequence == SubSequence.SubSequence を満たさないといけないんだけど
8:54 AM
SubSequenceAnySequence ならその条件を満たせるけど
Avatar
omochimetaru 5/23/2017 8:54 AM
はい
Avatar
SubSequenceAnySequence だと推論するためには prefix の戻り値が AnySequence であることが必要で
Avatar
単純にprefixじゃないほかのところからAnySequenceが推定されているのでは?
Avatar
その prefix を手に入れるためには SubSequence.SubSequence == SubSequence じゃないといけない
Avatar
全体確かめないと断定できなそうですが
Avatar
↑に例示したコードで十分鶏卵型推論が再現可能 (edited)
Avatar
@t.ae でも他のメソッドでも AnySequence 返すためには AnySequence 作らないといけなくて、そのためには結局 SubSequence.SubSequnece == SubSequence が必要なのでは? (edited)
Avatar
関係ないところで、SubSequenceを返す関数がAnySequenceのデフォルト実装が無制限に書いてあるのがあって
8:57 AM
それが伝播していれば不自然は無い、という話
8:57 AM
でも、 protocol A { associatedtype B func hoge(arg: B) } extension A where B == Void { func hoge(arg: Void) { // こっちはB無しでVoidが推論されるが } } これで再現可能なんで
8:57 AM
どうにも
Avatar
omochimetaru 5/23/2017 8:57 AM
@koher すいません、まだわからない点がある
Avatar
extension Sequence { /// Returns a subsequence, up to the given maximum length, containing the /// final elements of the sequence. /// /// The sequence must be finite. If the maximum length exceeds the number of /// elements in the sequence, the result contains all the elements in the /// sequence. /// /// let numbers = [1, 2, 3, 4, 5] /// print(numbers.suffix(2)) /// // Prints "[4, 5]" /// print(numbers.suffix(10)) /// // Prints "[1, 2, 3, 4, 5]" /// /// - Parameter maxLength: The maximum number of elements to return. The /// value of `maxLength` must be greater than or equal to zero. /// - Complexity: O(*n*), where *n* is the length of the sequence. public func suffix(_ maxLength: Int) -> AnySequence<Self.Iterator.Element> }
👍 1
Avatar
@tarunon なるほどー・
Avatar
omochimetaru 5/23/2017 8:58 AM
SubSequence.SubSequence == SubseqenceならそのAnySequenceを返すextensionが有効化するのはわかったけど
Avatar
suffixは無制限なのか、じゃあこれが伝播できますね
Avatar
omochimetaru 5/23/2017 8:58 AM
その、有効化したオーバーロードによって、 Sequence protocolが満たされる事自体は
8:58 AM
どうやって確認するの
Avatar
この extension はデフォルト実装はないの?? suffix は原理上無理か。
Avatar
omochimetaru 5/23/2017 8:59 AM
Sequenceを実装する型があるとき、それはSubSequenceを何かしら決めてるわけで
Avatar
@koher extensionなんで実装持ちですよこれは
8:59 AM
stdlibにソースがあるはず
Avatar
omochimetaru 5/23/2017 8:59 AM
で、その何かしら決まったSubSequenceにたいして、SubSequence.SubSequence == SubSequence が成り立っているなら
8:59 AM
そのAnySequenceを返す版も使えるようになる、protocol Sequenceの本体定義にあったfunc prefixとは関係ない
9:00 AM
って可能性は?
Avatar
あー、別に自分の SubSequence を使わなくても AnySequence 作れるのか。
Avatar
無宣言SequenceがSubSequence==AnySequenceで推論されるのは、suffixの実装から伝播してる、でFAな気がする
Avatar
ん? makeIterator 使うからやっぱ無理?
9:01 AM
なんで prefix のデフォルト実装には SubSequence.SubSequence == SubSequence が必要だったのに、 suffix だとその制約がなくてもデフォルト実装が書けるんですか?
Avatar
omochimetaru 5/23/2017 9:01 AM
AnySequenceは、makeIteratorをラップするクロージャで実装できるから、本当のSubSequenceが何かとは関係なく、いろんなケースで作れるのでは。
Avatar
AnyIteratorに包めば良さそう
Avatar
@omochimetaru その AnySequence にイニシャライザに渡せる Sequence の条件が SubSequence.SubSequence == SubSequence
Avatar
norio_nomura 5/23/2017 9:02 AM
@t.ae さんがあげてる extension Sequence { public func suffix(_ maxLength: Int) -> AnySequence<Iterator.Element> { } } により SubSequence == AnySequence<Iterator.Element> が推測されそうだ。 (edited)
Avatar
prefixpublic func prefix(_ maxLength: Int) -> AnySequence<Iterator.Element> { _precondition(maxLength >= 0, "Can't take a prefix of negative length from a sequence") if maxLength == 0 { return AnySequence(EmptyCollection<Iterator.Element>()) } return AnySequence( _PrefixSequence(_iterator: makeIterator(), maxLength: maxLength)) }makeIteratorAnySequence に渡すために SubSequence.SubSequence == SubSequence が必要で
9:04 AM
いや違う
9:04 AM
_PrefixSequence に渡すのに必要なのか (edited)
9:05 AM
うーん、まあ別にイテレートして取り出して適当な Sequence に入れられるんだから
9:05 AM
制約がなくても実装自体は普通に可能か。
Avatar
これが制約がガバで漏れ出てるのか、意図してるのかはよくわかんないですね
Avatar
ってか、 suffix だと一度全部読み出してみないと終わったかわからないから
9:07 AM
普通に Array とかに入れてそれを AnySequence にラップして返してるとかかな。
9:07 AM
とすると、本当ならそのまま Array で返してもいいのにわざわざ AnySequence としてるということは。「ガバで漏れ出てる」んじゃなくて「意図してる」っぽい気がする。
Avatar
omochimetaru 5/23/2017 9:09 AM
struct MyIterator<T> : IteratorProtocol { mutating func next() -> T? { return nil } } struct MySequence<T> : Sequence { func makeIterator() -> MyIterator<T> { return MyIterator() } } print(MySequence<Int>().prefix(2)) // AnySequence<Int>(_box: Swift._SequenceBox<Swift._PrefixSequence<__lldb_expr_68.MyIterator<Swift.Int>>>)
9:09 AM
とりあえず、何も書かなくてもAnySequenceを返す版が有効化してることは確かめられた
Avatar
suffix は?
9:10 AM
_PrefixSequence の部分が suffix でどうなるか見たい (edited)
Avatar
omochimetaru 5/23/2017 9:10 AM
print(MySequence<Int>().prefix(2)) print(MySequence<Int>().suffix(2)) AnySequence<Int>(_box: Swift._SequenceBox<Swift._PrefixSequence<__lldb_expr_77.MyIterator<Swift.Int>>>) AnySequence<Int>(_box: Swift._SequenceBox<Swift.Array<Swift.Int>>)
Avatar
お、やっぱ Array だ。
Avatar
omochimetaru 5/23/2017 9:11 AM
とりあえずこの実験で、AnySequenceのインスタンスが出てきてるってことは、さっきの SubSequence.SubSequence == SubSequence の条件のやつが有効化して、その有効化によって SubSequence == AnySequenceが確定して、 protocol Seuqnceが満たされるっていう ループが起きたってこと? (edited)
Avatar
norio_nomura 5/23/2017 9:11 AM
上でも書かれてる通り、 sufixwhereなしextensionだよ。
Avatar
ループではないけど、そう
9:12 AM
ただし
9:12 AM
そこら辺はバグがあるので、仮にsufixがwhereなしでも、同じムーブは起きる
Avatar
omochimetaru 5/23/2017 9:12 AM
この挙動が不思議だねって話題か。
9:12 AM
仮じゃなくてsuffixはwhere無しらしい
Avatar
バグがある、は言いすぎた。バグと思わしき挙動があって
9:12 AM
いや、僕の言ってるのは、もし仮に、sufixが縛られてても
9:13 AM
全く同じ動きになるよという話
Avatar
norio_nomura 5/23/2017 9:13 AM
@t.ae さんが見つけた extension Sequence { public func suffix(_ maxLength: Int) -> AnySequence<Iterator.Element> { } } これで決定だと思うのだけど。
Avatar
Sequenceだといろいろ生えててどこから来てるか分からないので最小で書いてみたほうがいい感
Avatar
omochimetaru 5/23/2017 9:13 AM
@norio_nomura とりあえず、prefixについては、そのようなシンプルなやつは無いんですよね?
Avatar
suffixwhere なし extension だから、そこから suffix の他の実装がなければ SubSequenceAnySequence であることが推論されて、その結果 prefix 等の extension の制約 SubSequence.SubSequence == SubSequence も満たして、 prefix 等も実装してることになると。
Avatar
norio_nomura 5/23/2017 9:14 AM
SubSequence == AnySequence<Iterator.Element> の仮定があればprefixも呼べるよね。
Avatar
omochimetaru 5/23/2017 9:15 AM
その仮定がどこから来てるかが謎って話ですよね
Avatar
norio_nomura 5/23/2017 9:15 AM
public func suffix(_ maxLength: Int) -> AnySequence<Iterator.Element> これ
Avatar
omochimetaru 5/23/2017 9:16 AM
あ!そういう話?!
Avatar
Sequenceはそいつが原因ですね
9:16 AM
それはそう
Avatar
@norio_nomura はい、それで決定だと思います。 prefix の実装には SubSequence.SubSequence == SubSequence を必要としたのに suffix でそれが必要ないのが不思議でしたが、前から読めばいい prefix と違って、どこで終わるかわからないから最後まで一度読み出さないといけない suffix だと _PrefixSequence みたいなのにラップしなくても Array に入れりゃいいので別に SubSequence.SubSequence == SubSequence を満たさなくても効率の良いデフォルト実装ができる。 (edited)
Avatar
@tarunon さんの言うバグは最小のでないと断言しづらいですね。
Avatar
omochimetaru 5/23/2017 9:17 AM
見逃していた、そういう話しか
9:18 AM
条件なしのextension Sequenceに、func suffixがあって、それが AnySequenceを返しているから、それによってSubSequenceがAnySequenceに決まって、それによってprefixのほうのwhereが通る
Avatar
そっちはそう、そのムーブは納得がいく
Avatar
omochimetaru 5/23/2017 9:18 AM
このムーブの発動条件はなんなんだ
Avatar
suffixの実装
9:19 AM
普遍的なextension Sequence { func suffix -> AnySequence } の存在が、
Avatar
omochimetaru 5/23/2017 9:19 AM
Sequenceを実装してる型を定義する時に、その型にsuffixを定義すればそれになって、定義しなかった場合に、普遍的なextension Sequenceの方にフォールバック?
Avatar
structなどの実装におけるfuncを定義してassoctypeを縛る挙動と等価
Avatar
omochimetaru 5/23/2017 9:19 AM
なるほど
9:21 AM
上でたるのんがあげてるVoidとか絡んだ亜空間推論ほどの事は起きてないって事ですかね
Avatar
もしかして、↓の Filtered もこんな感じでデフォルトが決まるようになるのかな? https://github.com/apple/swift-evolution/blob/master/proposals/0174-filter-range-replaceable.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
ですね
Avatar
omochimetaru 5/23/2017 9:21 AM
よかった、亜空間推論が仕様だったらどうしようかと思った
Avatar
これまでとの整合性を考えると Filtered のデフォルトは [Element] (edited)
Avatar
Add a Filtered associated type to Sequence,
9:22 AM
これ多分こっちもAnySequenceでは
Avatar
omochimetaru 5/23/2017 9:22 AM
Selfじゃないのかね
Avatar
あーArrayでいいのか
Avatar
でもこれまでデフォルト実装で filter ついてきて、その戻り値は [Element] でしたよね?
Avatar
omochimetaru 5/23/2017 9:22 AM
無理な場合があるのか
Avatar
Selfはinitできないと無理な気がする
9:23 AM
Sequenceはinitを条件に持ってないから辛そう
Avatar
omochimetaru 5/23/2017 9:23 AM
たしかに。そうだね
Avatar
@omochimetaru Self はデフォルト実装ないなら可能だけど、現行の Swift と整合性がなくなっちゃう。 Set とか ArraySlice とかの filter[Element] 返すし。
Avatar
Arrayの場合と、LazySequence<Self>がほしい場合があるのかな
Avatar
omochimetaru 5/23/2017 9:24 AM
@koher ああ、Arrayに寄っちゃう挙動とも整合取れないのか
Avatar
うん。
Avatar
norio_nomura 5/23/2017 9:25 AM
SE-0014 が実装されるまでは prefixwhere なし extension だったから、今日のきっかけの問題は両方で起きていた可能性があったのかな。 let a = [""].map { $0 }.prefix(3) let b = [""].prefix(3).map { $0 } // Ambiguous use of 'prefix' (edited)
Avatar
このfilter とか map とか、前から難しい問題だと思ってて、パフォーマンス考えて lazy にしたい場合と、利便性考えて [Element] 返したい場合があって、 Haskell みたいな遅延評価言語だとそのあたり全部 lazy かつ標準的なコレクションで統一されるのはいいなぁと思う。
Avatar
let b = [""].suffix(3).map { $0 } これは通る
9:28 AM
whereの制約見直さないと
Avatar
@t.ae 型推論の優先順位のルールがおかしいっぽいね。
9:29 AM
これおもしろいな。
Avatar
基本的にwhere句の制約は、制約が厳しい方が優先されるはず
Avatar
@koher Haskellのはいいですね。mapとか一通りArrayで返ってくるのが気になる
Avatar
1> [2, 3, 5].suffix(2).map { $0 } $R0: [Int] = 2 values { [0] = 3 [1] = 5 } 2> [2, 3, 5].prefix(2).map { $0 } error: repl.swift:2:1: error: ambiguous use of 'prefix' [2, 3, 5].prefix(2).map { $0 } ^ ↑ Swift のヤバさをよく表してる。 (edited)
Avatar
ArraySliceとAnySequenceのwhere句の制限が同じ重さだから、優先順位がつけられない
9:30 AM
suffixは宣言が無だから常にArraySliceが優先でOKっぽい
Avatar
@tarunon いや、違うんですよ。
Avatar
マジ
Avatar
↓これはいけるんです。この場合は ArraySlice 優先。 1> [""].prefix(3) $R0: ArraySlice<String> = 1 value { [0] = "" }
Avatar
あー
Avatar
後ろにmap が付くと同格になってあいまいになる。
Avatar
解釈がむずい
Avatar
なんか、複雑な CSS セレクタ書いてるときに、どっちが優先されるかわからなくなるのと同じような気分になる。
9:33 AM
さっきから何かに似てると思ってたけどそれだ。
Avatar
最小コード再現しようと思ったけどできないな
Avatar
norio_nomura 5/23/2017 9:37 AM
SE-0014 以前はどっちも普通に動いた。 sh-session $ /Library/Developer/Toolchains/swift-2.2-SNAPSHOT-2016-01-06-a.xctoolchain/usr/bin/swift Welcome to Apple Swift version 2.2-dev (LLVM 3ebdbb2c7e, Clang f66c5bb67b, Swift 54dcd16759). Type :help for assistance. 1> let a = [""].map { $0 }.prefix(3) 2. let b = [""].prefix(3).map { $0 } // Ambiguous use of 'prefix' a: ArraySlice<String> = 1 value { [0] = "" } b: [String] = 1 value { [0] = "" } (edited)
👍 2
9:39 AM
2.2の頃は SE-0014 関係なく普通に動いていた様にも見える。
9:39 AM
普遍的エクステンションと亜空間推論の同時定義をいろいろやってみた。
9:39 AM
いみふめい
Avatar
そうそう
9:40 AM
型推論優先ルール、束縛条件が強いほうが強いに則って、亜空間推論が普遍推論より優先されて
9:40 AM
超面白い
9:41 AM
返り値引数をassoctypeのalias名のまま書くと、亜空間推論は起きない
Avatar
あー普遍的なのじゃなくても流れてくるんですね
Avatar
omochimetaru 5/23/2017 9:42 AM
あ〜 AT1 で書くっていう選択肢もあるのかそうか
Avatar
普遍より亜空間が強いのは、制約が強いから普通じゃない?
Avatar
いや、それはそう
9:43 AM
そうなんですが、亜空間推論が成り立つのがただでさえおかしいのに
9:43 AM
普遍が殺されるのは輪をかけておもしろい
Avatar
omochimetaru 5/23/2017 9:44 AM
なんかこんなわけのわからないやつのほうが強くて良いのかという違和感がある
Avatar
亜空間推論は気持ち悪いですね。
9:44 AM
ああ、そういうことか。 < 亜空間推論が成り立つのがただでさえおかしいのに普遍が殺されるのは輪をかけておもしろい
Avatar
norio_nomura 5/23/2017 9:44 AM
print() に引きずられるのでは?
Avatar
protocol A { associatedtype B = String func hello() -> B } extension A where B == Int { func hello() -> Int { return 1 } } class C: A { } もっと面白いの
Avatar
omochimetaru 5/23/2017 9:45 AM
そうおもってhogeを切っておいたんですけどだめかな
Avatar
デフォルトの宣言が亜空間推論にかき消される
Avatar
これは String の場合のデフォルト実装がないからじゃないですか?
Avatar
そうです、コンパイルエラーになって欲しいところですが…
Avatar
指定が無い場合任意型になって任意のwhereを満たせると考えると分かりそうな気がする
Avatar
さすがに String の場合のデフォルト実装があったら String が勝ちますよね?
Avatar
protocol A { associatedtype B = String func hello() -> B } extension A where B == String { func hello() -> B { return "hello" } } extension A where B == Int { func hello() -> Int { return 1 } } class C: A { } C().hello()
9:46 AM
C().hello()の型はどっちでしょう
Avatar
え?これ String じゃないんですか?
Avatar
宣言が`hello() -> B
Avatar
あー、そこが違うのか
Avatar
になってるのがポイントで、これはIntが勝ちます
9:47 AM
BをStringにすると、引き分けのコンパイルエラー
9:47 AM
String優先してくれ頼む
Avatar
omochimetaru 5/23/2017 9:47 AM
wwww
Avatar
え、デフォルト設定してるのに優先されない?
9:47 AM
ひどい・・・
9:48 AM
associatedtype のデフォルトは闇が深そうだ
Avatar
omochimetaru 5/23/2017 9:48 AM
えっとじゃあ、ベストプラクティスとして
9:48 AM
extensionを実装する時の型名はエイリアス名のままにしておくのがよい?
Avatar
間違いなく
9:48 AM
それしないとどこから亜空間推論発生して型が崩壊するかわからない
Avatar
omochimetaru 5/23/2017 9:48 AM
そうだよね・・・
Avatar
なるほどー
Avatar
面白い。
10:03 AM
@omochimetaru さんの struct MagicDog : MagicProtocol {} のgistも全部 func getAT1Value() -> AT1 と書くと結果が変わる。
Avatar
AT1にすると優先されなくなりますね。
10:04 AM
そっちの挙動が僕がなんとなくそういう言語仕様だろうと思ってる方。
10:04 AM
亜空間のほうはバグなのでは???という気持ちが
10:04 AM
ある
Avatar
亜空間は流石にバグだと思う
Avatar
(しかしどちらも根拠レス)
Avatar
鶏卵問題解決できるのはどう考えても
10:05 AM
どう考えてもおかしい
Avatar
でも、亜空間同士の衝突は起きるから
10:05 AM
ちゃんと候補を列挙して、絞りこめるならそれを採用するっていう
10:05 AM
ロジックがちゃんと書いてある感じがして
10:05 AM
意図を感じる
Avatar
うーんそれは
10:05 AM
単純に優先順位同列の推論が衝突したときの
10:06 AM
エラーがそのまま出てる気がする、別にこれ専用に意図したものでは無いんじゃないかな
Avatar
じゃあ、AT1と書くか Int と書くかで、挙動が変わるのも、意図せずそうなってしまっただけ? (edited)
Avatar
その2つで挙動の差があるのはもうバグとしか思えない
Avatar
エイリアスを使わなかった場合に where が1個余分に評価されている様な感じ。
Avatar
Intって手書きしてる事で推論上の型変数がPolyTypeからConcreteTypeになっていて、解決済みの採用候補に間違ってぶちこまれるみたいな (edited)
Avatar
where句を無視してfunctionをあると仮定、その後にwhere句を採用して枝刈りみたいな (edited)
10:07 AM
そういう動きなのでは?とか想像してる
Avatar
protocol MagicProtocol { associatedtype AT1; func getAT1Value() -> AT1 } extension MagicProtocol { func getAT1Value() -> Array<Int> { return [1, 2, 3] } } extension MagicProtocol where AT1 == String { func getAT1Value() -> AT1 { return "AT1 is String" } } extension MagicProtocol where AT1 == Int { func getAT1Value() -> AT1 { return 32 } } struct MagicDog : MagicProtocol {} let dog = MagicDog().getAT1Value() // [1, 2, 3] まともだ
Avatar
ですね
Avatar
これも rotocol A { associatedtype B = String func hello() -> B } extension A where B == String { func hello() -> B { return "hello" } } extension A where B == Int { func hello() -> B { return 1 } } class C: A {} C().hello() // "hello"
Avatar
そう
10:27 AM
全部assoctypeで書いておけば平和です
Avatar
Hi 😄 I added Kotlin support for this project which is inspired from https://github.com/angelolloqui/SwiftKotlin and obviously, JavaプログラマのためのKotlin入門 - Qiita . Sorry for pushing a large commit, but ...
12:49 PM
いなみさん流石のムーブ
Avatar
この間ちゃんとしたKotlin触ったけどContextが鬼門だったなぁ
Avatar
Context?Androidの?
Avatar
そう
Avatar
それはKotlin関係ないやんけ
Avatar
鬼門なのはそれはそう・・・
12:52 PM
あれ一応意味があってすごくて
12:52 PM
同じプロセスの中で別のアプリからキックされたactivityが別画面として共存できるんだよね
12:52 PM
でもなんかいろんなテクニックとかアンチパターンとかいっぱいあって大変
Avatar
やばそう
12:57 PM
いろんなテクニックとかアンチパターンあるのはUIKitも一緒やな
12:57 PM
やっぱりそれを生業にしないと真の理解は得られなさそうだ
Avatar
SequenceAnySequenceを返すメソッドをArrayへ変える実験らしい https://github.com/apple/swift/pull/9639
This is an experiment to confirm that replacing AnySequence in default methods on Sequence with Array improves performance. This is a supporting argument to SE-NNNN Sequence Cleanup. At the moment,...
Avatar
@norio_nomura タイムリーですね👍
Avatar
AnySeqと違って溜め込むから単純に性能上がるとか言えるのか、、、?
Avatar
AnySeqだと動的ディスパッチで遅いとかもありますね
Avatar
@koher 上のいなみさんのやつみました?
Avatar
中身見てないです。
Avatar
スイフトスクリプトにプルリクが来てますよ
Avatar
Array にすると prefix が lazy にできないから
12:39 AM
ユースケース次第でパフォーマンス下がりそう。
Avatar
ですよねえ。
Avatar
その場合はSubSequenceをちゃんと指定して対処するんじゃないですか?
Avatar
>The lazy computation of prefix and dropFirst methods will be moved to LazySequence.
12:42 AM
とのこと
Avatar
やっぱりSubSequence型が定義されてるのに、普遍的にAnySequence(またはArray)が生えてるのは違和感があるなぁ
Avatar
where SubSequence == AnySequence<Element> だったらいいですよね。 (edited)
Avatar
それなら全く違和感はないですね、平和
Avatar
そもそもSubSequenceってSequenceにほんとうに必要なものなんですかね? ArrayArraySliceはパフォーマンス上分かるけどだいたいがSubSequence = Selfで済む気がする。
Avatar
Self はダメじゃない?
Avatar
omochimetaru 5/24/2017 2:23 AM
ArrayとArraySliceはパフォーマンス上分かるけどだいたいが
もうこれで必要性が十分確立するとおもう。
Avatar
Selfだとinit持ってないと実装が出来ないとか、色々困ったことになりそう
Avatar
omochimetaru 5/24/2017 2:24 AM
だいたいの場合についてはデフォルト実装があれば困らないし。
2:24 AM
特定の場合について高速になるために用意するっていうのは合理的
Avatar
@omochimetaru そこをSequence中じゃなくて外部に持っていけなかったのかなと
Avatar
例の constraint の条件が悪いのであって、 SubSequence == AnySequence<Element> なら問題ない気が。
Avatar
@t.ae そうするとprotocolとしてのうま味がなくなる (edited)
Avatar
ただ、 Sequence から Iterable を剥がして、 Iterable は純粋に makeIterator のみを持つでもいい気もしてる。
Avatar
それはあり得ますね
Avatar
ただ iterable にしたいだけなのに、変な map とか filter とかいっぱいついてきて鬱陶しいんですよね〜
2:26 AM
特に mapMapped がないから、戻り値 Array 版が強制で追加されるの嫌・・・
Avatar
Mappedできるとしても最短で5以降ですよね、言語機能が足りてないから
Avatar
ですね。
Avatar
omochimetaru 5/24/2017 2:27 AM
外に出すとどうなるかはパッとわからんなあ・・・
Avatar
Core Team も Higher-kinded type の優先度低そうな感じだったし。
Avatar
Mappedが出来れば、SequenceとOptionalの共通のベース型としてモナド型定義できないかな?と思ったけど現状Sequenceがinitできないから厳密な定義からは逸れてしまうか
Avatar
omochimetaru 5/24/2017 2:32 AM
昨日koherとその話をしたんだけど
2:32 AM
同じモナドを返すってところがうまくかけないんだよね
Avatar
@omochimetaru @tarunon さんはそのことはわかってて
2:33 AM
Higher-kinded type が必要なことがわかってて、それが導入されるなら早くても Swift 5 だろうなぁと
2:33 AM
で、それが導入されたらモナド作れそうってことだと思います。
Avatar
ですです
Avatar
omochimetaru 5/24/2017 2:34 AM
ふむふむ
Avatar
昨日の謎推論、ざっとbugs.swift見たけど報告上がってなさそうだな、あとで報告上げるかー (edited)
Avatar
うーん、なんとなくニュアンスの違いとして、挙動が違うのも理解できる気もするんですけどね。
Avatar
しかし、型が確定する材料が足りてないのに確定してしまうのはおかしい(はず)なので
2:59 AM
とりあえず報告はしていいと思いました
Avatar
亜空間推論の方ですか?
Avatar
omochimetaru 5/24/2017 3:01 AM
@tarunon どこ調べたらいいかわかんないしバグとして上げて回答貰えればそれはそれでという気持ちがある(迷惑かもしれないけど。 (edited)
Avatar
@koher ですです
Avatar
https://bugs.swift.org/browse/SR-4985 ざっくり、完結に、報告 done
👍 6
Avatar
norio_nomura 5/24/2017 1:14 PM
$ xcrun --toolchain org.swift.4020170523a swift Welcome to Apple Swift version 4.0-dev (LLVM 351dc0fd49, Clang 9cf11ef2d0, Swift 3ea9a3bac7). Type :help for assistance. 1> struct S {} 2. let mapped = zip([S()], [""]).map { 3. ((s, string)) -> S in s 4. } error: repl.swift:3:6: error: closure tuple parameter does not support destructuring ((s, string)) -> S in s ^~~~~~~~~~~ arg0 let (s, string) = arg0; Swift 4のタプル周りの変更、なかなか面倒だ。 (edited)
Avatar
TupleとArgumentsの差が明確になる君
1:37 PM
これ、(s,string)じゃなくてtupleとして引数を取れ、と言うことですか?
Avatar
そう見えますね。元々ネストしたタプルとかクロージャ式で destructure できなかったですし、それをサポートしてほしいんですよねぇ。
1:47 PM
何が嫌って、クロージャ式の冒頭で一度 destructure を入れると single expression にならなくなって、 return を書かないといけなくなったりするところですね。一つの式で同じプロパティに複数回アクセスするときに、タプルとして受けて foo.bar + (foo.baz / foo.bar) みたいに書くのも面倒ですし。
Avatar
返り値は無名のタプルで引数でラベリングするサボり術が死んだ
Avatar
norio_nomura 5/24/2017 2:03 PM
Dictionarymapとかで受け取るタプルにkey,valueってラベルがついてるのが便利だと見直されるかも。
2:03 PM
$0.key$0.0のどちらでもいけるし。
Avatar
ラベル付けて返り値作って、$0使うのが主流になるか、それはそれで良いかしら。
Avatar
なるほど、ここでラベル・・・
Avatar
switch tuple { case let (a, b): break default: break } こういうのもできなくなるんでしょうか?destructuring assignment とは違うかな?
Avatar
上のエラー見る限りはあくまでクロージャ引数でのタプルの destructuring ができないようにみえるけどどうなんだろう…
Avatar
ああ、たしかにclosure tuple parameter ~って書いてますね
Avatar
norio_nomura 5/25/2017 3:30 AM
swift-3.1-DEVELOPMENT-SNAPSHOT も出てる。
Avatar
昨日の @norio_nomura さんの話、タイムリーに関連する話題が Swift Evolution で流れてる。 https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170522/036773.html
9:20 AM
Apple の core lib チームの人(?)が SE-0110 に関連してこんな PR もらったんだけど、ほんとにこの変更( SE-0110 )いるの?って言ってる。
Avatar
norio_nomura 5/25/2017 9:32 AM
今それを言うか 😅
9:33 AM
swift-evolution のプロセスはうまくいっていない気がするなあ。
Avatar
omochimetaru 5/25/2017 9:34 AM
MLでやってるからでは・・・
Avatar
norio_nomura 5/25/2017 9:34 AM
ほんとそれ
Avatar
omochimetaru 5/25/2017 9:36 AM
適したサービスを使えば、タグフォローして通知とか、ホットなスレッドとか、興味ありそうな人を巻き込んだり、いろいろできるわけで
9:37 AM
いまはかなり能動的に動かないとリーチできないから、結果的にスルーしちゃって、後で直面してから受動的に反応することになってると思う
Avatar
iOS関連SlackでAppleの人が「Slack使いたいけど社内にインスタンスを立てられないと使えない」的なことを言ってたのを見かけたことがあるから、完全に外部依存のサービスは使えないのだろうなあ。 (追記: swift-evolutionとは関係ない文脈での言) (edited)
Avatar
マストドンかな?
😂 1
😰 1
Avatar
なるほど
Avatar
WWDCで何か発表があるといいなあ。
Avatar
「Apple製SNS、ここでなんでもできる!swift-evolutionもここでやるぜ」とか
Avatar
いや、そこまで期待してないw
Avatar
スラック買収しよう
10:04 AM
解決
Avatar
あいや「Slack使いたい」ってのはswift-evolutionとは関係ない文脈でした。
Avatar
なる
Avatar
昨日の SE-0110 の件、 Core Team の Joe Groff がここで話してたのと同じこと言ってる。 Furthermore, this probably comes up most commonly with dictionaries, since they're a sequence of tuples. The element tuple for dictionaries has element labels (key: Key, value: Value), so instead of writing `{ tuple in let (key, value) = tuple; f(key, value) }`, you could use the implicit argument and write `{ f($0.key, $0.value) }`. https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170522/036788.html
Avatar
そうですよね、そんな気がしてた
4:30 AM
ただどうしてもtupleを変数として宣言しないと辛いケースがままあって、そう言うときにvalとかtとかpairとかそういう変数名を付けざるを得ないのはちょい辛い
Avatar
それに対する Nate Cook さんのリプライ。 Dictionaries are definitely a common case for this, but zipped sequences and enumerated() sequences are also very common, and don't have labels attached.
4:33 AM
外国人、「さん」を付けるか迷う・・・。 Chris Lattner とか Steve Jobs に「さん」を付けるのは変だけど、 try! Swift のスピーカーとか、普通に会って話すかもしれない人に「さん」を付けないのも変だし、境界があいまい・・・。
Avatar
'@'は敬称ですよ
4:34 AM
と言うことにしておくと楽
Avatar
この解釈あるとめちゃくちゃ楽なんで流行って欲しい
4:35 AM
ので、意図的に@を使ってさん付けしないようにしている、でも端から見たら失礼な奴かなぁ
Avatar
そうですね。でも @ ついてても「さん」付けちゃうなぁw
4:37 AM
あ、「そうですね」は「流行って欲しい」に対してです💦
Avatar
おもちさんに誘われて参加しました。よろしくお願いします。
Avatar
おお、 @giginet さん、よろしくお願いします。
Avatar
失礼な奴と思われてもこれが正義だと信じてるんで!僕は自分の信念に従って(ry
4:39 AM
海外はMrとかMsとか面倒くさすぎるからsan楽で超良いねって聞いたけど、githubとか見てると@で済んでる場合が多い感
Avatar
ビジネスとかだと面倒かもだけど、 GitHub や Twitter は @ で済みそうですね。
Avatar
よろしくおねがいしますー
4:41 AM
チャットとかでも最近は @ でメンション飛ぶし @ で済ませたいですね…
Avatar
@slightair よろしくお願いします。 (edited)
4:42 AM
さっきの Nate Cook さんのメールの内、 Chris Lattner への返信の部分。 The only confusion I've ever seen from users is when deconstruction didn't work enough, like if the parameter was (Int, (Int, Int)) and you couldn't destructure the nested tuple.
4:44 AM
普通にクロージャでもタプルを受けられりゃ問題解決なんだよなぁ。 dictionary.forEach { (key, value) in ... } が問題なんであって、 dictionary.forEach { ((key, value)) in ... } はできていいと思うんだけど。
Avatar
それは出来て欲しいんですが、今もそれ相当の構文は書けなくて辛かった
4:45 AM
Rxでscan書いてるときにありがちですね、タプルがネストして片方をpairとか雑な名前で宣言しちゃう
Avatar
なので、これまでルーズな構文に頼ってきただけで、ルーズなのが良くないってのと、↑ができないってのと二つの問題があって、ルーズな方だけ封じたから面倒になったってだけな気がする。
4:46 AM
タプルがネストして片方をpairとか雑な名前で宣言しちゃう
これ困りますよねぇ。
4:47 AM
真面目に { fooAndBar in let (foo, bar) = fooAndBar ... } とか書くのも微妙だし。
Avatar
$0, $1 ... への自動デストラクト なくせばいいと思った。
4:48 AM
let dict: [String:Int] = [:] let ary1 = dict.map { ($0, $1) } let ary2 = dict.map { $0 } たしかにこれはわかりにくいし。
Avatar
↓これは今回ので禁止されないんですか? let ary1 = dict.map { ($0, $1) }
Avatar
禁止されます。
Avatar
ですよね。
Avatar
Swift3 の状態から $0, $1 ... への展開だけなくすだけで、いいんじゃないかと。 (edited)
Avatar
なるほど。
4:51 AM
まあ確かに foo.map { x in ... }foo.map { (x) in ... } が同じ以上、 dict.map { ((k, v)) in ... } を認めてしまったら dict.map { (k, v) in ... } はそれと同じじゃないのか、ってなるのかな?
4:52 AM
タプルなのか引数なのか区別できない。
Avatar
それが同じなのはギルティなんで外すのでは?
Avatar
上の二つは区別されないんじゃないですか? Swift 4 でも。
Avatar
え。。。
Avatar
だって foo.map { (x: Bar) -> Baz in ... } は生きてますよね?
Avatar
そっちはOKで
4:53 AM
foo.map { x -> Baze in ... } こいつは殺さなきゃいけない
Avatar
されないと思いますよ。 { x, y in ... } パラメータが括弧で囲まれてなかったら暗黙の括弧がつくというルール
Avatar
と、思ってた
4:53 AM
Ohhh
Avatar
元々は関数の引数はタプルと等価だったから、 { (x, y) in ... }(x, y) がタプルなのか引数なのかという区別はなかったけど、それを区別したから今度は記法として区別できなくなっちゃったのか。 (edited)
4:56 AM
でも、タプルを分解したい場合は必ず {((x, y)) in ... } でいいと思いますけどねぇ・・・。
Avatar
その場合に、 { ( (x: Int, y: Int) ) in を認めるのかっていう議論がでちゃいますね。 { ( (x, y): (Int, Int) ) in } のほうが正当。
Avatar
後者だけで良いのでは
Avatar
なるほど。そもそも現状は関数宣言時の引数のフォーマットを踏襲しているわけで、そこにタプルの分解を持ち込んだときにどういう記法とするのかは議論が必要そうですね。
5:03 AM
{ ( (x: Int, y: Int) ) in ... } にしても { ( (x, y): (Int, Int) ) in ... } にしても関数宣言の記法にない新しいものを追加しようとしてるわけですし。
5:04 AM
↓はできるんだからそれを踏襲すればいいのかな。 let (a, (b, c)) = (2, (3, 5))
5:05 AM
let (a, (b, c)): (Int, (Int, Int)) = (2, (3, 5))
5:05 AM
だからやっぱ後者がいいのかな。
Avatar
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160530/019578.html とりあえず一年前のラトナーはそれを認める気はないようです。
5:06 AM
クロージャの話ではないけど。
Avatar
なるほどー。まあでも利用頻度はクロージャ式の方が圧倒的に高そうだから、クロージャ式でも絶対になしかというと微妙なところですね。
5:09 AM
let (a: Int, (b: Float, c: String)) = (2, (3.0, "5")) 的な書き方は、全く別の意味になるのでやっぱりナシですね。
5:09 AM
↑は前話してたやつで、結果は↓。 Int: Int = 2 Float: Double = 3 String: String = "5"
5:10 AM
↑の記法でラベル( a, b, c )が付けられてるの意味不明だけど。 (edited)
Avatar
CHANGELOG より: Type annotations are no longer allowed in patterns and are considered part of the outlying declaration. This means that code previously written as: var (a : Int, b : Float) = foo() needs to be written as: var (a, b) : (Int, Float) = foo() if an explicit type annotation is needed. The former syntax was ambiguous with tuple element labels. (20167393)
Avatar
これってどの Proposal で決定されたんですか?
Avatar
Swift2.0 での変更なので、オープンソース前です。
Avatar
ああ、 2016 年じゃないんですね。後ろが日付じゃなかった・・・。
Avatar
omochimetaru 5/26/2017 6:27 AM
やっと話題に追いついたw
6:27 AM
カッコの話題はスマホからじゃ読めねえ
6:28 AM
そもそも現状は関数宣言時の引数のフォーマットを踏襲しているわけで、そこにタプルの分解を持ち込んだときにどういう記法とするのかは議論が必要
まさにまさに
Avatar
この間の @rintaro のself書き換えでNib/Stroyboardのinstantiateが書けたけど
やっぱりpropertyとしてletを置けないので価値はそこまで高くない感じ https://github.com/tarunon/Instantiate/pull/20
8:43 AM
🙇
8:44 AM
引用のやり方を覚えていない…
Avatar
omochimetaru 5/26/2017 8:44 AM
コードの左のところをクリック。
Avatar
コードの左がわからなかった(´ . .̫ . `)
8:49 AM
行番号をクリック。
Avatar
あいやそっちじゃないw
8:49 AM
それはわかる
8:49 AM
Discordの引用
Avatar
omochimetaru 5/26/2017 8:50 AM
Discordは引用が無いと思う。
8:51 AM
リプライ2種類あると思ってたらこれは、自分宛てかそうじゃないか、か
Avatar
ああ、オレンジの線わかりづらいですよね。
Avatar
omochimetaru 5/26/2017 8:51 AM
@omochimetaru test
8:51 AM
あ〜
Avatar
Discord の Slack に対するネガティブ要素は引用わかりづらいことなんですよね。
8:52 AM
最近はさっきの ML の引用みたいにコードブロックにすることも・・・。
Avatar
コードブロック万能説
Avatar
いや、入れ子になるとダメなので限界があります。
Avatar
あー
Avatar
さっきのinitでfunc呼びたい話、static funcなら安全に納得できるかな、と思ってたけどclass funcをSelfで使えないからちょっと辛い class Cat { let a: Int let b: Int let c: Int init(){ a=1 b=a+1 c=Self.makeC(a: a, b: b)//<-だめ } class func makeC(a: Int, b: Int)->Int { return a+b } } print(Cat().c)
Avatar
Cat.makeCはクラス名変更があるから嫌ってこと?
Avatar
オーバーライドできないから、欲求を全て満たせない
Avatar
typealias ThisClass = Cat とか
11:15 AM
ああ。
Avatar
type(of: self)
Avatar
今丁度それ見つけたんですが
11:15 AM
self初期化してないのに通るんですねw
Avatar
type(of:) は特別ですからねー
11:16 AM
https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md これが結局実装されてないから、 Self が使えない。
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
まだ4には入って来ないです?
Avatar
なるほど
Avatar
4 で実装される気配は今のところないです。 https://github.com/apple/swift/pull/3866 一回頓挫してから気配なし。
What's in this pull request? Implementation start on SE-0068. This does not yet implement allowing Self to refer to the dynamic type in non final classes outside of function signatures, just expan...
Avatar
ぬぬぬ、そうなんですねorz ありがとうございます
Avatar
やはりclassは日陰者…
Avatar
structこそ至高
😁 1
Avatar
最近Viewもfinal付けて作るようになって、極力classの酷い扱いの被害を受けないように意識して立ち回るようになってしまった
Avatar
そんなに継承被害があったんですか( ゚д゚)
Avatar
protocolのパワーを引き出そうとすればするほど、final classにせざるを得ない…
11:28 AM
UIImage、finalじゃなくて本当に勘弁して欲しい感じなんですがどうするのが正解だろう…
11:28 AM
struct Image作ってラップした方がいいかなぁ
11:31 AM
final class Image: UIImageという天命を得たけどこれは正解か…?はて…
Avatar
なるほど、final付けることで性質が変わるんですねあんまり意識したことなかったです
Avatar
protocolにstatic func定義して、Selfを返してこれにデフォルト実装を持たせる、とすると、final classじゃないと実装できなくなります。これは多分上のSelfのサポートが緩いためだと思う。
11:41 AM
あとはrequired initの絡みとか、最近話題になったinitのバグ周りとか、辛い場面が多い印象です。
Avatar
確にrequired initじゃないとダメなケースは遭遇した記憶、ログおってみます
Avatar
UIImageはクラスクラスタじゃない?
Avatar
あー、そうですね、そうだ…
11:54 AM
struct Image標準で欲しいけど、これUIKitだから無理そう
Avatar
iOS-Runtime-Headers - iOS Objective-C headers as derived from runtime introspection
iOS-Runtime-Headers - iOS Objective-C headers as derived from runtime introspection
Avatar
お、 structImage がほしい人のための https://github.com/koher/EasyImagy
EasyImagy - Makes it easy to deal with images in Swift
Avatar
!!!
2:32 PM
欲しかった奴だ
Avatar
UIImage との相互変換もできるし、CoWも効いてます。
Avatar
ありがとうございます!!
2:33 PM
めっちゃいい
2:33 PM
最高だった
Avatar
ただ、APIをGuideline準拠しようとして放置中なんですよねー。
Avatar
なるほど
Avatar
あと、 RGBA をジェネリクス化したい。
Avatar
他のカラースペースで実装できるようにする、とかですかね
Avatar
UInt8 だけじゃなくて Int とか Double とかとれるように。
Avatar
ああ、
Avatar
protocol Myself {} extension Myself { var `Self`: Self.Type { return type(of: self) } static var `Self`: Self.Type { return self } } class Foo: Myself { func bar() { Self.hoge() } static func baz() { Self.hoge() } static func hoge() { print("called") } } rizumitaさんがこんなの薦めてくれました
Avatar
omochimetaru 5/26/2017 6:16 PM
Selfをシャドーしてる・・・
Avatar
omochimetaru 5/27/2017 8:47 AM
@takasek こっちに移しておきますね
モダンなSwiftのExtension ですけど、 UIColor.hoge は view.backgroundColor = .hoge できるけど UIColor.ex.hoge は view.backgroundColor = .ex.hoge できないってどうなんですかね?
8:48 AM
RxSwiftがやってるみたいに、extensionを .rx 以下で生やすと、それを左辺に取る代入文の右辺側で型名を省略する . 記法ができないのどう思うって話題
8:48 AM
個人的には、そもそもできたら良い気がする。
Avatar
それ出来るとすると、多段にネストしてもできるのが成り立つはずで
Avatar
omochimetaru 5/27/2017 8:49 AM
せやね
Avatar
そうすると推論が成り立たないケースも出てきそう
Avatar
omochimetaru 5/27/2017 8:49 AM
.hoge ってやってるときってさ、
8:49 AM
左辺の型の型名以外無いんだっけ。
8:49 AM
view.backgroundColor = .red とかやってるときって、 . の左に来るのって UIColor 以外ありえない?
Avatar
型情報は左辺型に束縛されてるだけ
Avatar
omochimetaru 5/27/2017 8:50 AM
もしありえないなら、ドットから始まってるなら、左辺の型を置いてみるだけでよくて、その先が .red だろうが .piyo.hoge.fuga だろうが、難しさが変わらないように思う
Avatar
でもUIColorならサブクラスがあり得そうだけど
Avatar
omochimetaru 5/27/2017 8:52 AM
class Cat { static var mike: Cat { return Cat() } } class FireCat : Cat { static var garo: Cat { return FireCat() } } class Person { var cat: Cat? } let p = Person() p.cat = .mike // ok p.cat = .garo // error
Avatar
この場合はそもそもFireCatを推測するのが不可能になってる、それは、左辺値がCatでしかないから
Avatar
omochimetaru 5/27/2017 8:53 AM
UIColorならサブクラスがあり得そうだけど
これをそのまま読んだ
(edited)
Avatar
代入するの自体は、 FireCat.mikeでもFireCat.garoでも出来て、省略は出来ない
8:55 AM
ネストした場合も一意に辿り着けるのかな (edited)
8:56 AM
動きとしては、.開始なら左辺の型を割り当てて呼ぶだけ、ということなら愚直にやって普通に動きそうだ
Avatar
omochimetaru 5/27/2017 8:57 AM
だよねえ、そんな気がするんだよね
Avatar
ただ、今不思議に思ったのは
Avatar
: T = .A.B.C のときに、 T { var A: T { get } var B: T { get } var C: T { get } } みたいに常にTのチェーンだけサポートするなら、底からから辿れば良いけど、この件含めそうではないので、 .C -> T を持つ型群を検索、その型群すべてに B が その型を返す型を検索...ってなって、推論が O(全型数^深さ) になっちゃうんじゃないかな。 (edited)
Avatar
これp.catはCat?だから、普通に考えたら無理だよね、.をOptional<Cat>で埋めても、mikeは居ないはず。Optionalは特別扱い?
Avatar
omochimetaru 5/27/2017 9:05 AM
推論が O(全型数^深さ) になっちゃう
ここがよくわからないです。 左辺が T で、 .A が来るので、 T.A を探す、見つかる → T.A は :T で .B が続くから T.B , -> T.Bは :T で .C が続くから T.C -> T.C は :T で代入できるのでOK と、 一直線に進む気が。
Avatar
ああ、 T から始まるならそうか。ですね。
🙂 1
Avatar
omochimetaru 5/27/2017 9:07 AM
@tarunon 例のごとくそうやろうね、 この .推論について T? からのときだけ T も探すんだろう
9:07 AM
@tarunon もしサブタイプ一般に探すなら、さっきの例で FireCat も探してくれないとおかしいし。
Avatar
Cat???????とかやっても通る?
Avatar
omochimetaru 5/27/2017 9:11 AM
class Cat { static var mike: Cat { return Cat() } } class FireCat : Cat { static var garo: Cat { return FireCat() } } class Person { var cat: Cat?????? } let p = Person() p.cat = .mike print(p)
9:11 AM
通った
Avatar
通るのかww
9:11 AM
Optionalの特別扱い、再帰的な処理になってそう
9:12 AM
だから、サブタイプも含めて探すような作りだと、底から探さなきゃいけなくてめちゃくちゃ時間がかかるはずで
9:13 AM
staticなTしか成り立たないのは、頭にTを乗せて探してるだけ(OptionalはWrapped)ということ
9:13 AM
であればextension以下も探せるはず、かなぁ
Avatar
omochimetaru 5/27/2017 9:15 AM
それかなんか見落としてる探索要素があって、多段にすると爆発しちゃうからできないか。
Avatar
底から探してるかな?と思っててextension付けちゃうと爆発しそうと思ってたけど、今の作りは頭から行ってるから
Avatar
norio_nomura 5/27/2017 9:52 AM
多段ありにするとめっちゃビルドが遅くなりそう。 (edited)
Avatar
norio_nomura 5/27/2017 1:57 PM
Swift 4のSwiftPMはPackage@swift-4.swiftというファイルがある場合、Package.swiftの代わりにそれを使う。しかしパッケージマニフェストのバージョンをPackage.swiftの1行目 // swift-tools-version:N.N (記述がなければデフォルトの3.0)から取得しそれを使ってしまうバグがある。 https://bugs.swift.org/browse/SR-5031
2:00 PM
これがファイル内で指定されたマニフェストバージョンを正しく使う様に修正されれば、Swift 3.xでビルドできる状態をPackage.swiftで維持したまま、Swift 4では拡張されたマニフェストの記述をPackage@swift-4.swiftで使える様になる。 (edited)
2:01 PM
例えばブランチ指定とか。
Avatar
うちのSwift3.0.2なんですけど、こっちだとOptionalの再帰的解決ないみたいですねー。 class Person { var cat: Cat?????? } let p = Person() p.cat = .mike // error: type 'Cat??????' has no member 'mike'
Avatar
クロージャ式でのタプルの分解、将来的にありえそう?↓ Core Team の John McCall 。 > Personally I agree that closures worth their own syntax and that it is important to keep closure's syntax lightweight. So, IMO we should keep {x, y in ..} syntax for closures and this should be jut equivalent for {(x, y) in ..}, i.e. one can use first or second depending on his/her style. > > I think the idea of double parentheses for tuple argument destructing in closure is the best solution as it has a relationship to introduced by SE-0066 type of function with tuple argument. I.e. : Yes, I agree. We need to add back tuple destructuring in closure parameter lists because this is a serious usability regression. If we're reluctant to just "do the right thing" to handle the ambiguity of (a,b), we should at least allow it via unambiguous syntax like ((a,b)). I do think that we should just "do the right thing", however, with my biggest concern being whether there's any reasonable way to achieve that in 4.0. https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170522/036846.html
Avatar
func foo<T>(_ body: (Int) -> T) -> T { return body(42) } func foo<T>(_ body: () -> T) -> T { return body() } let result: String = foo { arg in print(arg + 12) return "test" } 今日これがXcode8.3.2 でタイプチェック通らない(ambigous)ことにムカッときたけど Swift4 では通ったので、たぶん SE-0110 の良い影響なんだと思いました。 (edited)
Avatar
これ推論出来るのすごい
Avatar
omochimetaru 5/29/2017 3:14 AM
あ〜。<Void>にせずにちゃんと潰そうとすると曖昧になるやつw
Avatar
Void+Intを外に定義したらambigousになりますかね
Avatar
omochimetaru 5/29/2017 3:14 AM
そういうの考えてくとタプル分解とかも結構罠あるのかな
Avatar
SE-0110 じゃないかもしれないけど、Swift3 では (_ body: () -> T)(_ body: (Void) -> T) と同義になっちゃっているっぽいんですよね。 (edited)
Avatar
3:18 AM
Swift4だと()と(Void)が別になるんですか
3:18 AM
ああ、そこでタプルが出てくるのか
3:18 AM
なるほど
Avatar
func testCopy_BLAS() { let stride = 2 let c = 100_000_000 let a = [Float](repeating: 1, count: c) var b = [Float](repeating: 0, count: c/stride) measure { cblas_scopy(Int32(c/stride), a, Int32(stride), &b, 1) } } func testCopy_vDSP() { let stride = 2 let c = 100_000_000 let a = [Float](repeating: 1, count: c) var b = [Float](repeating: 0, count: c/stride) measure { vDSP_mmov(a, &b, vDSP_Length(c/stride), 1, vDSP_Length(stride), 1) } } vDSPって内部はBLASなんじゃないのと思ってたんですがベクトルコピーはvDSPのほうが速かった。 vDSPの方はストライド二倍にすると所要時間が半分になるけどBLASはそこまで行かない。
4:35 AM
vDSPはマイナスストライド使えないんですが下手するとvDSP_vrvrs呼んだほうが速いレベル
Avatar
protocolの中で、static func some() -> Self と宣言するのと、 initを作るの、明らかに後者の方が強いということがわかった
7:27 AM
static funcをprotocol extensionに実装した場合、必ずstatic funcになる(class funcにできない)ので、Selfの返り値が実装を宣言したクラスに固定されて、final classであることが強制される (edited)
7:27 AM
一方でinitはrequired initの扱いになって、返り値はSelfに決定されるので、サブクラス化が可能だった (edited)
Avatar
Argo ってそんな風になってなかったっけと思って見てみたら一度 associatedtype を経由してたけど、これは同じことになるのかな? https://github.com/thoughtbot/Argo/blob/master/Sources/Argo/Types/Decodable.swift
Argo - Functional JSON parsing library for Swift
Avatar
omochimetaru 5/29/2017 7:30 AM
protocol P1 { static func a() -> Self } class Animal { static func a() -> Self { fatalError() } }
7:30 AM
protocolの中のSelfを、conformする側でもSelfで受ければ同じ事じゃない?
Avatar
いや、それだと全てのclassに実装する必要があって
7:30 AM
弱い
7:31 AM
protocol extensionで一般的な実装を提供したい
7:31 AM
Argoのassoctypeは、Swift2.
7:31 AM
Swift2.x時代の名残か、Genericsに渡すために必要かのどちらかだと思います
Avatar
お、そんな制約がある/あったんですね。
Avatar
Himotokiのdecode funcはもしかしたら、init(decode extractor: Extractor) に出来るかもしれない。
Avatar
Unboxはinitで定義されてた記憶
Avatar
omochimetaru 5/29/2017 7:36 AM
protocol P1 { static func a() -> Self init() } class Animal : P1 { required init() {} static func a() -> Self { fatalError() } } class Vehicle : P1 { required init() {} } extension P1 { static func a() -> Self { return Self.init() } } できそうでできなかった。これ P1 の a が Vehicleについて見つけてくれないのなんでだ。
Avatar
protocol Decodable { static func decode(_ json: JSON) -> Decoded<Self> } こうすると、Decodableを実装した型がfinal classであることを強制されるように見えますね、そうすると既存の型を拡張できなくなる
7:36 AM
@omochimetaru Vehicleをfinalにしてみて
Avatar
omochimetaru 5/29/2017 7:37 AM
ほんとだ〜いけた〜・・・
Avatar
そう、今回見つけたのはまさにそれで
7:38 AM
protocol Foo { static func generate() -> Self } extension Foo { init() { self = Self.generate() } } protocol Bar { init() } extension Bar { static func generate() -> Self { return Self() } }
7:39 AM
このFooとBarの差異
7:39 AM
Fooの実装はサブクラスを持てないが、Barの実装はサブクラスを持てる
7:40 AM
そこに、initであってもprotocol extensionに実装を記述することが可能、を組み合わせると
7:40 AM
✌('ω' )✌ > Swift楽しい < ✌( 'ω')✌
7:40 AM
となるわけです
Avatar
omochimetaru 5/29/2017 7:41 AM
なんかコンストラクタ周りのObjCとの繋ぎ込みでガチャガチャやった結果な感じがするなあw
7:42 AM
static funcがextension以下で、classであることがわかっていてもclass funcにできない、Selfが実装時の型に固定されるというのが、バギーかな、という気がしている
Avatar
initであってもprotocol extensionに実装を記述することが可能
これってprotocolのみの話であってます?
Avatar
protocol extensionに記述したinitは、class struct enum, そして protocolを実装したclassのsubclassで使うことが出来ます。 (edited)
8:04 AM
これはちょっといじるとまた新しいバグが見つかりそうだなw
Avatar
omochimetaru 5/29/2017 8:06 AM
/Users/omochi/work/sandbox/HogeGround.playground:8:5: Protocol extension initializer never chained to 'self.init'
8:06 AM
なるほど
8:06 AM
protocol extensionの中のinitは、他のself.initを呼ばないといけないんね (edited)
Avatar
それか、selfに外から値をぶち込むか
Avatar
omochimetaru 5/29/2017 8:07 AM
出た・・・
Avatar
required' initializer in non-class type 'Log (edited)
Avatar
self = ...でOK
Avatar
omochimetaru 5/29/2017 8:09 AM
self = に代入できるのはSelf型なんだね
Avatar
んだべ
Avatar
おお、行けた protocol Log: Unboxable { // ... } extension Log { required init(unboxer: Unboxer) { try! self.init(unboxer: unboxer) } } (edited)
8:14 AM
間にTranslatorがいれば嬉しさが増すのかな
8:21 AM
final class良いですね...乱用したい
Avatar
あー
8:30 AM
Himotokiはやっぱ、initを呼ぶ時にoptionalになっちゃってるのをErrorにうまいこと逃がすことが出来なくなってしまう、のでダメっぽい
8:31 AM
class の initがOptionalの時に詰んでしまうな。
Avatar
throwsなinitでwrapすれば可能?
Avatar
throwsなinitでOptional initをラップすることが出来ない、ですね
8:36 AM
これやろうとすると、protocol extensionのinitでself置換、の裏技を採用しないと作れないw
8:38 AM
Himotoki - A type-safe JSON decoding library purely written in Swift
8:38 AM
URLがstructになってるから、既存のテストについてはパスするけど、
8:38 AM
classでOptional initを持ってる場合、はもうちょっと込み入った実装をしなきゃいけなくて、一概に良いとは言えない感じ
Avatar
Dictionary Literal 書いてて、条件によって一部のエントリーを外したいようなことってないですか?
Avatar
ある
Avatar
val foo = [ "a": 2, "b": 3, "c": 5 if bar == baz ] みたいな
8:58 AM
まあ、今書いてるのは Kotlin なんですがw
8:58 AM
なんかいい方法ないでしょうか?
Avatar
タプルの(key, value)からinit出来るDictionary extensionを書いておいて
8:59 AM
Dictionary.init( [Optionalな(key, value)].flatMap { $0 } )
8:59 AM
これがおすすめでしょうか
Avatar
なるほど。ありがとうございます。
Avatar
[(key, value)]からinit出来るようにしておくと、Dictionary.init(Dictionary.filter { ... })みたいな事もできて頗る捗るので
9:00 AM
超おすすめです
9:01 AM
Swift4で追加されないかな
Avatar
dictionaryLiteralはなぜかありますよね
9:02 AM
ああこれもしかしてExpressibleByDictionaryLiteralからきてるのか
9:03 AM
なんで可変長だけあるんだろうと思っていました
Avatar
Swift 可変長引数に Array 渡せなくて困る。なんかやり方あるんでしたっけ?
9:14 AM
↓みたいな感じでできた。この * (配列を可変長引数に展開)が Swift にもほしい。 // Kotlin mapOf(*(arrayOf( "foo" to obj.foo, "bar" to obj.bar, obj.baz?.let { "baz" to it } ).flatMap { if (it == null) emptyList() else listOf(it) }.toTypedArray())) (edited)
Avatar
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/033190.html SE-172 One-sided Ranges の絡みでsyntax についての議論がまとまらず。
Avatar
可変長引数からArrayに渡すのはできるんですけどね
Avatar
なるほど。 ... から離れれば良いような気も
Avatar
omochimetaru 5/29/2017 9:28 AM
Many programming languages have some sort of Apply function, a language construct that applies a function to a list of arguments. Apply is ubiquitous in functionally-leaning languages, but it is ...
9:28 AM
func apply<T, U>(fn: (T...) -> U, args: [T]) -> U { typealias FunctionType = [T] -> U return unsafeBitCast(fn, FunctionType.self)(args) }
9:28 AM
怪しい・・・
Avatar
すごいハックだw
Avatar
なるほど、そっち側の変換があったか
Avatar
omochimetaru 5/29/2017 9:28 AM
// You can call apply with many different variadic functions apply(average, [1.5, 2.5, 5.0]) // -> 3.0 apply(sum, [1, 2, 3]) // -> 6
Avatar
unsafeBitCastw
Avatar
やーべえw
Avatar
omochimetaru 5/29/2017 9:28 AM
一応できてる・・・
Avatar
func apply<T, U>(fn: (T...) -> U, args: [T]) -> U { typealias Fn = ([T]) -> U return unsafeBitCast(fn, to: Fn.self)(args) } let dict = apply(fn: Dictionary.init, args: ["a": 1, "b": 2, "c": 3].filter { $0.value % 2 == 0 }) print(dict) // ["b": 2] いけますね…
9:32 AM
まじかー
Avatar
これは便利
Avatar
func apply<T, U>(fn: @escaping (T...) -> U, args: [T]) -> U { typealias Fn = ([T]) -> U return (fn as! Fn)(args) } let dict = apply(fn: Dictionary.init, args: ["a": 1, "b": 2, "c": 3].filter { $0.value % 2 == 0 }) print(dict) unsafeBitCastいらんかった
Avatar
あれ、キャストでいけちゃうんですね
Avatar
これと
Avatar
omochimetaru 5/29/2017 9:43 AM
as! なのか・・・
Avatar
あとなんか、@escapingつけないとダメだったのもよくわからん
Avatar
↓こっちの方が好みかも。 func fix<T, U>(_ f: @escaping (T...) -> U) -> ([T]) -> U { return f as! ([T]) -> U } let dict: [String: Int] = fix(Dictionary.init)([ ("a", 2), ("b", 3), ("c", 5) ]) (edited)
Avatar
let x: (Int...) -> Int? = { (a: Int...) in return a.first } typealias Fn = ([Int]) -> Int? x as? Fn // nil 謎いw
Avatar
norio_nomura 5/30/2017 3:51 AM
public init<S: Sequence>( uniqueKeysWithValues keysAndValues: S ) where S.Iterator.Element == (Key, Value) {
👍 1
Avatar
ほしい
Avatar
norio_nomura 5/30/2017 4:07 AM
swift-4.0-branchはWWDC始まるまでロックされたままかな?
4:11 AM
REPLの:type lookup Dictionaryだと、書式が違うな。 init<S>(uniqueKeysWithValues keysAndValues: S) where S : Sequence, S.Element == (Key, Value)
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
norio_nomura 5/30/2017 4:13 AM
ですです。こんなのも public init<S: Sequence>( _ keysAndValues: S, uniquingKeysWith combine: (Value, Value) throws -> Value ) rethrows where S.Iterator.Element == (Key, Value) { public init<S: Sequence>( grouping values: S, by keyForValue: (S.Iterator.Element) throws -> Key ) rethrows where Value == [S.Iterator.Element] { (edited)
Avatar
おお
4:18 AM
便利だ
4:20 AM
昨日の話の続き、 let x: (Int...) -> Int? = { (a: Int...) in return a.first } type(of: x) // <- ((Array<Int>) -> Optional<Int>).Type
4:20 AM
型的には同じらしい
Avatar
omochimetaru 5/30/2017 4:20 AM
お〜〜
4:20 AM
でもまあ現バージョンがたまたまそうなってるだけの可能性があるからなあ。
Avatar
let x: (Int...) -> Int? = { (a: Int...) in return a.first } typealias Fn = (Array<Int>) -> Optional<Int> print(type(of: x)) // (Array<Int>) -> Optional<Int> print(x as? Fn) // nil
4:22 AM
これが完全に解せない
Avatar
先のapplyに入れればキャストが可能
4:23 AM
なんかありそう
Avatar
↓もダメでした。 func fix<T, U>(_ f: @escaping (T...) -> U) -> ([T]) -> U { // cannot convert return expression of type '(T...) -> U' to return type '([T]) -> U' return f } func fix<T, U>(_ f: @escaping (T...) -> U) -> ([T]) -> U { // cannot convert value of type '(T...) -> U' to type '([_]) -> _' in coercion return f as ([T]) -> U } (edited)
Avatar
as!だけOKなんですよね
4:25 AM
実行時の型は同じだが、asでの変換は不可能で、素のままでやるとキャストもfailする。が、Genericsな型に変換して渡したあとならas!でキャストが可能
Avatar
@tarunon さんのコードの続き print(x is Fn) // false
Avatar
あーー
4:25 AM
これってもしかして
4:25 AM
暗黙の変換系のアレでは
Avatar
type(of:) がおかしいだけな気も
Avatar
func foo(x: Int...) { print(x) } let _foo = foo as Any as? ([Int]) -> Void _foo?([1,2,3]) いったん Any 通すと大丈夫っていう。
Avatar
ええw
Avatar
ってことは
4:26 AM
type(of:)がおかしいから
4:27 AM
as?がコケてる説
Avatar
そもそも as! で変換できるのに as?nil ってありですっけ?
Avatar
いや
4:28 AM
Anyを通さないとas!も失敗します
4:28 AM
AnyやGenericsパラメータを通すと、変換可能になる
Avatar
omochimetaru 5/30/2017 4:33 AM
ありそうな話ではある
Avatar
func foo(x: [Int]) { print(x) } let _foo = foo as AnyObject as? (Int...) -> Void _foo?(1,2,3) 逆も可とw
Avatar
omochimetaru 5/30/2017 4:34 AM
仕様としてはごちゃごちゃしてるけど、そういう柔軟なやつに入れた時には型情報つきのオブジェクトになってそう
4:34 AM
...に変換するのヤバwww
Avatar
逆が生成出来るなら、[(Key, Value)]をデフォルトでおいといて(Key, Value)...に変換するほうが合理的では?と思った
4:35 AM
てか
Avatar
Any じゃなくて AnyObject になったのは何か理由があるんですか?
Avatar
(Key, Value)...って受け手側はArrayなんだからそのままでよい
Avatar
AnyObject は、それでも通るかどうか試しただけです。
Avatar
なるほどです。
4:39 AM
うーん、なんで↓は Any 介さなくても通るんだろう。 func fix<T, U>(_ f: @escaping (T...) -> U) -> ([T]) -> U { return f as! ([T]) -> U }
Avatar
これは (T...) -> UAnyと同等の役割を果たしていそう
Avatar
↓コンパイル通るけど実行時に死ぬ。 let makeDict: ((String, Int)...) -> [String: Int] = Dictionary.init let dict: [String: Int] = (makeDict as! ([(String, Int)]) -> [String: Int])([ ("a", 2), ("b", 3), ("c", 5) ]) print(dict)
Avatar
let foo: (Int ...)->() = { x in print(x) } let _foo = foo as Any 元がクロージャだとコンパイラクラッシュ。うーん、可変引数クロージャは触らない方が安全だ。 (edited)
4:43 AM
Avatar
可変長引数複雑すぎるから全部配列リテラルで書けばいい気がする・・・
Avatar
配列リテラル用意しておいて、可変長引数はそれのシンタックスシュガーでいいと思うんですよ
4:46 AM
そっちの方が幸せな気がする
Avatar
norio_nomura 5/30/2017 4:46 AM
func variadic<T>(values: T...) { } let arr = [1, 2, 3, 4, 5] variadic(arr) Tの型は何?
Avatar
[Int]では
Avatar
omochimetaru 5/30/2017 4:47 AM
配列を可変長の1要素に書いて一包狂うやつ
4:47 AM
個人的にはスプレッドオペレータがさっさと欲しい
Avatar
norio_nomura 5/30/2017 4:48 AM
配列を可変長引数に変換できる様にすると、それが困ると言う投稿を読みました。 https://devforums.apple.com/message/974316#974316 (edited)
4:51 AM
$ echo "func f(a:Int...){}"|swiftc -emit-sil -|swift-demangle 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>>>): %2 = integer_literal $Builtin.Int32, 0 // user: %3 %3 = struct $Int32 (%2 : $Builtin.Int32) // user: %4 return %3 : $Int32 // id: %4 } // end sil function 'main' // f(a:) sil hidden @main.f(a: Swift.Int...) -> () : $@convention(thin) (@owned Array<Int>) -> () { // %0 // users: %2, %1 bb0(%0 : $Array<Int>): debug_value %0 : $Array<Int>, let, name "a", argno 1 // id: %1 release_value %0 : $Array<Int> // id: %2 %3 = tuple () // user: %4 return %3 : $() // id: %4 } // end sil function 'main.f(a: Swift.Int...) -> ()'
4:51 AM
内部的にはArrayらしい。
Avatar
逆な気もしますが、可変長引数と配列を同一視すると曖昧性があるのは確かです。 func foo(_ xs: [Int]) { ... } foo([2, 3, 5]) foo(2, 3, 5) // == foo([2, 3, 5]) foo([2]) // == foo([2]) or foo([[2]]) ???
4:52 AM
なので、不便を解消するにはスプレッドオペレータを導入するか、僕はむしろ最初から可変長引数なんてなくてもいいんじゃないかという気がします。
4:52 AM
[] 書くだけだし。
4:53 AM
ただ、今の Swift からなくすのは辛いから、スプレッドオペレータが現実解な気が。
4:53 AM
でも Any 経由で変換できるのは、最悪の場合のワークアラウンドとしては良さそう?
Avatar
omochimetaru 5/30/2017 4:54 AM
print(1,2,3)とprint([1,2,3])の意味が違うのは嬉しい
4:54 AM
前者は3つの値を表示せよ、で、それぞれの区切り方とかはprintに任されてるけど
4:54 AM
後者は「配列を表示する」場合っていうニュアンスが入っちゃう
Avatar
なるほど。別の形としてオーバーロードして
4:55 AM
意味を変えてしまうというユースケースがあると。
Avatar
omochimetaru 5/30/2017 4:55 AM
JavaScriptでconsole.debug(x, y, z) とかも、デバッガでその変数を表示したりするんで意味が変わる
Avatar
名前を変える( Swift ならラベルを変える)でいい気も。 (edited)
4:56 AM
まあでも、今更可変長引数取り除くのは現実的じゃないと思うんで、スプレッドオペレータがほしいのは間違いないです。
Avatar
omochimetaru 5/30/2017 4:56 AM
*array...array がメジャーですね
Avatar
で、 ... はレンジとの兼ね合いで流れたって話だったから、 * か、もしくは独自のキーワードでもいいかも?
Avatar
omochimetaru 5/30/2017 4:58 AM
#spread(array)
Avatar
それありなら #tuple(1, 2, 3)にすれば平和になるのでは
Avatar
@koher たとえばこういう? func foo(_ x: Int...) {} foo(...: [1,2,3]) func bar(baz x: Int...) {} bar(...baz: [1,2,3])
Avatar
omochimetaru 5/30/2017 5:00 AM
ラベル側を使うのおもしろい
5:00 AM
...: ←スネークっぽい
Avatar
・が多くて見づらいw
5:03 AM
名前を変える( Swift ならラベルを変える)でいい気も
ああ、受け側でオーバーロードするっていう意味ですね。呼び出し側かと思った。
Avatar
norio_nomura 5/30/2017 5:04 AM
可変長引数をArrayで作成したいシーンって、そんなに多い?
Avatar
可変長引数を使いたいケースの方が少ないくらいです
Avatar
omochimetaru 5/30/2017 5:05 AM
今回の話題の発端は Dictionary Literal だから
5:05 AM
そもそもタプル配列を取るやつを用意してくれって感じ
5:06 AM
JavaScriptだと Array.concat と スプレッドオペレータを組み合わせて flatten の代わりにするというイディオムがあるけど
5:06 AM
まともな標準ライブラリならそんなシチュエーションが生じない
Avatar
はい、そうです。 < オーバーロード
Avatar
norio_nomura 5/30/2017 5:08 AM
ならばSwift 4では不要かな。>スプレッドオペレータ (edited)
Avatar
まともな標準ライブラリ
これは常に可変長版と Array 版がオーバーロードされてるってこと?
Avatar
omochimetaru 5/30/2017 5:10 AM
JSの例で言えばflattenがあれば良かっただけなんですが、一般的にはそうですね
Avatar
(名前かラベルか変えないと曖昧性を生むから厳密にはオーバーロードでないけど)
5:11 AM
うーん、その 2 種類を用意するのはボイラープレート感あるから、やっぱり特殊構文がほしい気が。
5:11 AM
スプレッドなのか、 rintaro さんの言うような呼び出し側で切り替えるなのか。
Avatar
norio_nomura 5/30/2017 5:29 AM
Dictionary.init(dictionaryLiteral:) の説明文に Do not call this initializer directly. It is called by the compiler to handle dictionary literals. ってあるけど、実際困る様な事が起きたりするのだろうか。 (edited)
Avatar
うーん、将来的にシグネチャが変えられる可能性があるとか?
🤔 1
Avatar
norio_nomura 5/30/2017 6:23 AM
swift-4.0-branchはWWDC始まるまでロックされたままかな?
6月1日にmasterから再度swift-4.0-branchが切られるから、masterブランチに注力って事らしい。 https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20170417/004405.html
(edited)
Avatar
Do not call this initializer directly. これliteral系は全部書いてますね
7:48 AM
コンパイラの機能が成長して、stdlibに存在しなくても使えるようになって消滅する可能性がある、のかな
Avatar
norio_nomura 5/30/2017 1:16 PM
特に根拠となる文章やコミットは見つけられなかった。> Do not call…
Avatar
norio_nomura 5/31/2017 3:55 AM
ある型がSequenceに準拠しなくなったので代わりにallプロパティを使って欲しい、というメッセージをビルド時に出力する方法は無いものか。
3:58 AM
無理ぽ
Avatar
素直な方法無い気がする
4:02 AM
map/filter/flatMapみたいなよく使われるメソッドに@available書いてall.map/all.filter/all.flatMapに誘導するのは出来そう
Avatar
extension自体に@availableはできないんですね。
Avatar
norio_nomura 5/31/2017 4:03 AM
プロトコル準拠の宣言自体に@available()をつけることが出来ないですね。
Avatar
Kotlin 書いてるんだけど、 varList (タイミング問題でコンストラクタで初期化できない)と valMutableList (ミュータブルにしたいけどインスタンス自体は差し替えたくない)と valList を使い分けてて辛い・・・。 Swift で var と letArray` のミュータビリティをコントロールできるのほんと素晴らしい。 (edited)
Avatar
omochimetaru 6/1/2017 3:31 AM
varのListは要ります? コンストラクタは常にMutableListだけにして、変数はvalだけにして
3:31 AM
Listは返り値からの推論だけにすると
3:31 AM
気楽になりそう
Avatar
KotlinのMutableList、varに代入し直した時にSwiftと似たような挙動(CoW然り)になるんですか?
Avatar
omochimetaru 6/1/2017 3:32 AM
Kotlinのvarは単に参照がmutableというだけ。NSMutableArrayと同じよ。
Avatar
インスタンスは全部同じになるのかな
Avatar
イミュータブルであることを示したいけど(実際にはリードオンリーだけど)、コンストラクタのタイミングでは初期化できないから、プロパティとしては var になっちゃう。 by 使ったらうまくできんのかな?
Avatar
omochimetaru 6/1/2017 3:36 AM
lateinit valは?
3:36 AM
lateinitはvarにしか使えなかった・・・
Avatar
@tarunon Swift とは全く違う挙動ですね。単に型がわかれてるだけで全部参照型です。 var, valvat, let と同じです。
Avatar
@omochimetaru lateinit val, めちゃくちゃなフロー解析が必要になりそう
3:37 AM
うおお
Avatar
omochimetaru 6/1/2017 3:38 AM
structらくちんだよなあ
Avatar
全部 struct にしてプロトコル型変数も禁じたら(サブタイピングを排除したら)、 Haskell みたいな世界を築きながら、値型のミュータビリティの恩恵も受けられる。
3:40 AM
純粋値型言語。おもしろそう。
Avatar
for incase マッチ使えるの始めて知った。 enum E { case foo(String) case bar(Int) } let arry: [E] = [.foo("hello"), .bar(1), .foo("world!")] for case let .foo(str) in arry { print(str) }
Avatar
omochimetaru 6/1/2017 3:46 AM
ワオ
Avatar
pythonみを感じるw
Avatar
omochimetaru 6/1/2017 3:47 AM
.map と .filter のリスト内包表記みたい
3:47 AM
@tarunon それ
3:47 AM
右から左に修飾する宣言的記述は嫌でござる
Avatar
使いどころが思いつかないw
Avatar
これ出来るってことは、[UIViewController]から特定の型のUIViewController取り出せるかな。
Avatar
それなら、 for vc in vcs where vc is MyVC { ... } でいいとおもいます。
Avatar
omochimetaru 6/1/2017 3:53 AM
vcs.flatMap { $0 as? HogeViewController }
Avatar
whereも使えるのかw
3:53 AM
pythonみ高いなぁ
Avatar
omochimetaru 6/1/2017 3:54 AM
whereなら右にあるからまだ読める
Avatar
omochimetaru 6/1/2017 4:06 AM
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
4:07 AM
JavaScriptのArray.concatが T または Array<T> の可変個の引数で、型付けが面白い
4:08 AM
他の言語のチャンネルつくっとこ
Avatar
ios-developers-japan だけど他の言語チャネル作るの?w
4:10 AM
iOS Developer のための、他の言語チャネルだと矛盾しないか
Avatar
omochimetaru 6/1/2017 4:10 AM
矛盾しないし、そもそもWebViewとかもあるから TypeScript/ JSとかは普通に使う
Avatar
なるほど。
Avatar
omochimetaru 6/1/2017 4:11 AM
kotlinは・・・kotlin/Nativeとかあるし・・・
Avatar
4:11 AM
そのうち developers-japan になってたりしてw
Avatar
norio_nomura 6/1/2017 4:23 AM
for caseの利用例を探したらこんなのが。 open class NSMutableOrderedSet : NSOrderedSet { open func intersectSet(_ other: Set<AnyHashable>) { for case let item as AnyHashable in self where !other.contains(item) { remove(item) } } }
Avatar
for item: AnyHashable in self { じゃだめなんだろうか?
Avatar
omochimetaru 6/1/2017 4:26 AM
NSMutableOrderedSetの中に as AnyHashableが通らない (=Hashable)でない要素が入ってる可能性があるの・・・?
4:27 AM
実際には入ってないはずだけど型保証が無くて通らないからそう書いてるのかな
Avatar
実際には入ってないはずだけど型保証が無くて通らないからそう書いてるのかな
で正解っぽい。
😧 1
Avatar
norio_nomura 6/1/2017 4:32 AM
for item: AnyHashable in self { ?
Avatar
@norio_nomura この場合はだめですね。
Avatar
@available(*, unavailable) になってるスコープの中でunavailableなものを触っててもコンパイル通してほしいんだけどそういうふうに鳴らないかなあ
6:30 AM
@available(*, unavailable) struct Hoge { static var shared: Hoge = { fatalError() }() // error: 'Hoge' is unavailable }
6:32 AM
もっと広い範囲での提案。
Avatar
same-fileか。
6:33 AM
rintaroさんシュッとpitchが出て来るのすごい…
Avatar
似たような要望があったなってのを思い出しただけです。
Avatar
protocol側に逃がせばコンパイルエラー出ないように出来る気がする
Avatar
お?
Avatar
ゴリ押し感高いけどw
Avatar
omochimetaru 6/1/2017 6:34 AM
@available(*, unavailable) ってどういうとき使うの @hiragram
6:34 AM
コメントアウトして全部消しちゃえ
Avatar
アプリのメジャーバージョンアップとかで画面ごと無くなるみたいなときとかVCとVMをunavailableにしたりしてるけどまあ (edited)
6:36 AM
消せの気持ちはわかる。
Avatar
omochimetaru 6/1/2017 6:36 AM
あ〜
Avatar
@hiragram protocol UnavailableHoge { static var shared: Self { get } } extension UnavailableHoge { static var shared: Self { fatalError() } } @available(*, unavailable) struct Hoge: UnavailableHoge { }
6:36 AM
ほい
Avatar
omochimetaru 6/1/2017 6:36 AM
コンパイル通る状態で取っておきたいけど使ってる場所は洗い出したいのか
Avatar
gitの履歴とか遡るのがだるくて、かつ前のバージョンでどう実装してたっけ〜とコードが見たくなるときはある
6:36 AM
UnavailableHoge !!!!!!
Avatar
omochimetaru 6/1/2017 6:37 AM
一回コメントアウトしてからアプリをコンパイルして、エラーが大量に出るので、それを全部解決した後で、コメントインすれば?
Avatar
@availableはrenamed入れておくとコンパイラの加護を得られたりして大変良いので
Avatar
あとは @available(*, unavailable, renamed: "hogehoge") を結構やる
6:38 AM
そうそう
Avatar
特にチームでやっててリファクタリングと機能追加がかぶったりすると
6:38 AM
やってあげると超親切、ですね
Avatar
omochimetaru 6/1/2017 6:38 AM
renameなるほど・・・
Avatar
自分のブランチで消したら他の人が新しく呼び出したりしてそうなときとかはdeprecatedとかunavailableとかガンガンつけてやがて消すよというのをアッピルしてる
Avatar
omochimetaru 6/1/2017 6:39 AM
本当には消えてないほうが段階的に消せて便利なのか
Avatar
単に呼び出し先が無い(unresolved identifier)とかだとマージミスったかなとかそういうことを勘ぐりはじめてしまいがち
Avatar
omochimetaru 6/1/2017 6:39 AM
なるほど
Avatar
deprecatedでリネーム→マージしたあとでwarning掃除→unavailable/削除
6:40 AM
がおすすめ
Avatar
ふむ
Avatar
norio_nomura 6/1/2017 7:40 AM
^⌥⌘F
Avatar
omochimetaru 6/1/2017 7:41 AM
Ctrl + Alt + Cmd + F
Avatar
norio_nomura 6/1/2017 7:45 AM
確かCLIで実行する方法の話題がSwiftJPで出たはず。
Avatar
class A { class func foo(x: A) { print(x) } } class B: A { override class func foo(x: A?) { print(x) } } こいつは通るのに
9:39 AM
class A { class func foo(x: A) { print(x) } } class B: A { override class func foo(x: B) { print(x) } } こいつダメなの最高に納得がいかないw
Avatar
omochimetaru 6/1/2017 9:41 AM
ああ〜
Avatar
あー
Avatar
omochimetaru 6/1/2017 9:42 AM
うーんでもどうなんだろう
Avatar
サブタイプの関係が逆化
Avatar
omochimetaru 6/1/2017 9:43 AM
あ、ほんとだ
Avatar
protocol X {} class A: X { class func foo(x: A) { print(x) } } class B: A { override class func foo(x: X) { print(x) } } でもこれもダメなんだよね
9:43 AM
Optionalだけ謎の挙動がある
Avatar
omochimetaru 6/1/2017 9:43 AM
A? を受ける版は Aを受けることができるけど、Bを受ける版でAは受けれないわ。
9:44 AM
でもたとえば
9:45 AM
protocol X {} protocol Y {} class A: X, Y { class func foo(x: A) { print(x) } } class B: A { override class func foo(x: X) { print(x) } override class func foo(x: Y) { print(x) } }
9:45 AM
こういうことがおきたとき、どっちでオーバーライドするか決められないし?
Avatar
確かにそれはそうか
9:45 AM
Optionalはなんで通るんだ
Avatar
omochimetaru 6/1/2017 9:45 AM
そこのほうが気に食わない。
9:46 AM
参照型のOptionalがバイナリ互換だからかと思ったけどstructで試しても同じだった。
Avatar
バグっぽい
Avatar
A lot of people reported bugs in this area so it's worth mentioning that Swift now allows subclasses to override methods in a base class with a more general type.
Avatar
omochimetaru 6/1/2017 9:47 AM
あれ?
9:48 AM
NookとBedの例は
9:48 AM
あ〜クラスならいけるのかな?
Avatar
protocol は、まだだと思います。
Avatar
なるほど
Avatar
omochimetaru 6/1/2017 9:50 AM
class Animal {} class Cat: Animal {} class Vehicle { class func hit(_ x: Cat) {} } class Uaz : Vehicle { // 両方かくとエラー、どっちかだけなら通る。 override class func hit(_ x: Animal) {} override class func hit(_ x: Cat?) {} }
9:51 AM
↑こんな感じだった。
9:51 AM
片方にoverride,片方にoverride無し、なら、オーバライドする方を固定できるかと思ったが、「二回定義してるエラー」と「overrideついてないよエラー」が出て、ダメ。 (edited)
Avatar
あーー
10:00 AM
class A { class func foo(x: A) { print(x) } } class B: A { override class func foo(x: A??????) { print(x) } } 許して貰えなかったw
Avatar
omochimetaru 6/1/2017 10:00 AM
ww
Avatar
そこらへん闇で、一般的にはオーバーライド時に引数の型をゆるめることはできるんだけど、そもそも Swift の Foo?Foo が代入できるのはサブタイピングじゃなくて暗黙の型変換だから、それがオーバーライドでサブタイピングっぽく振る舞うのが闇で、実装するだけならコンパイル通るけど実行するとクラッシュとかあった気が。
Avatar
ひぇ
Avatar
おもしろいこと発見した。 まず、Swift↓は当然の結果。 // Swift var title: String = "a" class Foo { var title: String = "x" init() { title = "b" } } let foo = Foo() print(title) print(foo.title) a b そして Kotlin 。 // Kotlin var title: String = "a" class Foo { var title: String = "x" init { title = "b" } } val foo = Foo() println(title) println(foo.title) b x (edited)
Avatar
kotlinはthisでしたっけ?
Avatar
はい
Avatar
明示すれば正常になるのかな
Avatar
はい、なります。
Avatar
なるほど~
Avatar
Kotlin では常にローカル変数が優先されるようです。
6:45 AM
最初↓を試してたんですけど、 // Kotlin class Foo(var title: String = "x") var title: String = "a" val foo = Foo().apply { title = "b" } println(title) println(foo.title)
6:46 AM
apply に渡すラムダ式の中では暗黙的に this が使えるんですけど
Avatar
ローカル変数が無い場合はコンパイルエラーですか?
Avatar
↑のようにローカル変数があるとローカル変数に上書きされることがわかって、
6:46 AM
調査してると常にローカル変数優先だとわかりました。
6:47 AM
ローカル変数がないと↓です。 class Foo(var title: String = "x") val foo = Foo().apply { title = "b" } println(foo.title) b
Avatar
これはやだなw
Avatar
title が暗黙的に this.title を指します。
6:48 AM
まあ、 apply の件では明示的に宣言されているローカル変数が勝つというのがわからんでもないのと、 this. には this. を書けばアクセスできるんだからシャドーイングを考えてローカル変数優先ってことなんですかね・・・。
Avatar
外を優先するのはそれはそれでいいんですが
Avatar
AndroidStudioはメンバの色変わりましたっけ? Xcodeは変わるので安心感ある。
Avatar
その場合はthisの省略を許可しないでほしい
Avatar
applythis を省略できる Function Literals with Receiver って仕組みで、これはこれで便利なんですよね〜。
6:51 AM
↓を // Java primaryStage.setTitle("Hello World!"); Button btn = new Button(); btn.setText("Say 'Hello World'"); btn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { System.out.println("Hello World!"); } }); StackPane root = new StackPane(); root.getChildren().add(btn); primaryStage.setScene(new Scene(root, 300, 250)); primaryStage.show(); ↓みたいに書ける。 // Kotlin primaryStage.apply { title = "Hello World!" scene = Scene(StackPane().apply { children.add(Button().apply { text = "Say 'Hello World'" onAction = EventHandler<ActionEvent> { println("Hello World!") } }) }, 300.0, 250.0) show() } (edited)
Avatar
omochimetaru 6/2/2017 6:52 AM
ビルダーパターンなんていらんかったんや ってやつですね
Avatar
うん
Avatar
@t.ae 見逃してた。
AndroidStudioはメンバの色変わりましたっけ
どうだっけ? Try Kotlin では変わってないから変わらなさそうな気がする。
9:10 AM
( Try Kotlin は IDEA を踏襲してそう。で、 Android Studio も IDEA だから。) (edited)
Avatar
omochimetaru 6/2/2017 9:11 AM
変わった気がするけどなあ 基本的にASはEclipseの上位互換に思う
Avatar
いまちょうどやってましたけど変わりますね
Avatar
omochimetaru 6/2/2017 9:13 AM
それに加えてshadowing warningも出ない?
Avatar
おお、 Try Kotlin がしょぼいだけなのか。
Avatar
@omochimetaru shadowing waringはでないっぽいですね
Avatar
norio_nomura 6/2/2017 1:56 PM
イニシャライザでクラスクラスタを実現できないの、swift-corelibs-foundationにとって大きな障害ぽい。
Avatar
Protocol extensionで…と思ったけど、overrideできなくなるのはそれはそれで困るか
Avatar
class clusterがconvenience initになってサブクラスにpublic initが置けなくなるの、困るシチュエーションあるかな
Avatar
norio_nomura 6/2/2017 2:32 PM
おおお、イケるかも。
Avatar
オッ
2:33 PM
そもそもclass clusterは、open classには成れない気がする。ので、多分問題がない、かな
2:33 PM
強いて言えばあやしいかもぐらい
Avatar
https://github.com/apple/swift/pull/4087 放置PRですが。本体の方のFoudationオーバーレイにPR出してみた反応です。
What's in this pull request? I'm not sure this can be accepted or not. But this is convenient in some cases. Using that: Simplify copy constructor of NSSet and NSDictionary Eliminate getVaList fro...
🙂 1
Avatar
将来的には、classで普遍的にSelfが使えるようになれば、そっちにシフトしていけばいいはずなんで (edited)
2:43 PM
言語機能として再現不可能な状態に陥ることは無いかな?とは思ってるけどどうなんだろ
2:43 PM
やっぱりinitが欲しいのかな
Avatar
norio_nomura 6/2/2017 3:01 PM
最新のスナップショットでも使えるから直されていないのね。
Avatar
お、おもろいの見つけた
3:11 PM
import Foundation class Piyo<H>: NSObject { } class Hoge: NSObject { } extension Hoge { func hello() -> Piyo<String> { fatalError() } } class Fuga: Hoge { override func hello() -> Piyo<String> { // Declerations from extensions cannot be overriden yet return Piyo() } }
3:11 PM
これなんだけど、メソッドがobjcから参照可能な型なら通るっぽい
3:11 PM
import Foundation class Hoge: NSObject { } extension Hoge { func hello() -> AnyObject { fatalError() } } class Fuga: Hoge { override func hello() -> AnyObject { return "hello" as AnyObject } } Fuga().hello() ↑のでこれは通る
3:12 PM
RxSwiftにこれで通してる部分があるな
Avatar
norio_nomura 6/2/2017 3:15 PM
NSNumber.init(value: Bool)__NSCFBooleanを返す様にする https://github.com/apple/swift-corelibs-foundation/compare/master...norio-nomura:nn-fix-sr-4907
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
Avatar
めっちゃスッキリしてる
Avatar
norio_nomura 6/2/2017 3:18 PM
元々はNSNumber.objCTypeへアクセスしてクラッシュするバグを修正するのが目的なのだけれど、クラッシュしない場合にdarwinと同じ値を返す様にしたら、ピタゴラ的に追加修正が必要に… (edited)
Avatar
norio_nomura 6/3/2017 1:43 PM
_Factoryプロトコル使ったやつ、PR出してみた。 https://github.com/apple/swift-corelibs-foundation/pull/1025
Fixes SR-4907 Add TestNSNumber.test_objCType() reproducing crash Expected results are sampled from macOS Fix crash on accessing objCType property of NSNumber Change NSNumber.objCType to returning...
Avatar
classのinitでselfに代入が許可されない合理性考えてるけどイマイチ答えが出て来ない
6:30 AM
convenience initならself代入が可、で良いのでは?という気持ちがある
Avatar
加えて、failable initializerの場合 self = nil ではなく return nil
6:32 AM
するのもなかなか気になります
Avatar
failableだとnilなのかthrowなのか一瞬解らなくなるw
6:34 AM
nilableもthrowableもありますね
6:34 AM
nilable initからthrowable initに変換したいが、class initだとどうしても出来ない、と言うのが不便 (edited)
6:35 AM
protocol extension経由したら可能ですが、それは最早何やってるか解らんですね
6:36 AM
evolution書くしか
Avatar
@takasek Failable Initializerのnilは失敗したときだからreturnで早期脱出したいニーズがあるんだと思います。
10:22 AM
あー、あとnil代入できるためにはselfがOptionalじゃないといけないから、initの中でselfが使いにくくなりそうです。self?.fooってやらないといけなくなるので。
10:24 AM
return self はできてもいい気がしますけどね。成功ケースの早期脱出のために。
Avatar
↑の「Optionalじゃないといけない」は、Implicitly Unwrapped Optional扱いならいい気がしてきました。
Avatar
omochimetaru 6/4/2017 10:40 AM
static func init() -> Self? { var self = alloc() <プログラマが書く部分> return self } (edited)
10:41 AM
こういう感じに思ってる
Avatar
うん、それなら self= nil できない説明はつくけど、 return self できないのは謎。
Avatar
throw Errorとreturn nilだけ出来ますねぇ
Avatar
omochimetaru 6/4/2017 11:46 AM
たしかに。
Avatar
norio_nomura 6/4/2017 12:43 PM
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170116/030522.html
I think assigning to ‘self’ should be permitted in all convenience initializers, even initializers defined directly classes, without the protocol extension trick. Also, we should lower this more efficiently than we do today, without creating a self ‘carcass’ that is allocated and immediately freed, to be replaced by the ‘real’ self.
Avatar
classでProtocol extensionでハックすると、一瞬selfインスタンスができるってことですかね?alloc自体は走っている?
1:58 PM
あーそっか、swiftで書けるのはdeinitであってdeallocではない、前実験したときはdeinitしか見てなかった
Avatar
この前の Kotlin のローカル変数とシャドーイングの話、グローバル変数なら Swift と同じ結果になった。 // Kotlin var title: String = "a" class Foo { var title: String = "x" init { title = "b" } } fun main(args: Array<String>) { val foo = Foo() println(title) println(foo.title) } a b (edited)
2:53 AM
ローカルだとローカル優先。 // Kotlin fun main(args: Array<String>) { var title: String = "a" class Foo(var title: String = "x") { init { title = "b" } } val foo = Foo() println(title) println(foo.title) } b x (edited)
Avatar
omochimetaru 6/5/2017 2:53 AM
実行コンテキストでない静的なクラス定義でグローバル変数をキャプチャされたらつらいし妥当感
2:53 AM
というか、グローバル変数ってキャプチャする必要がないな
Avatar
逆に、グローバル変数って常にキャプチャされてるようなものじゃない?
Avatar
omochimetaru 6/5/2017 2:55 AM
まあグローバルスコープが一個あるって考える事もできますね
Avatar
↓例のクロージャ式でのタプルのdestructuringについて、Chris LattnerからJohn McCallへ。 One way to split the difference here is to eliminate the splatting behavior, but keep the destructuring (irrefutable pattern matching) behavior as well. In these cases, just require an extra explicit paren for the parameter list. This would change the diff's to: Example 1 - return columns.index { (column, _) in column.lowercased() == lowercaseName } + return columns.index { ((column, _)) in column.lowercased() == lowercaseName } Example 2 : - .map { (mappedColumn, baseColumn) -> (Int, String) in + .map { ((mappedColumn, baseColumn)) -> (Int, String) in Example 3 : - .map { (table, columns) in "\(table)(\(columns.sorted().joined(separator: ", ")))" } + .map { ((table, columns)) in "\(table)(\(columns.sorted().joined(separator: ", ")))" } Example 4 : - dictionary.first { (column, value) in column.lowercased() == orderedColumn.lowercased() } + dictionary.first { ((column, value)) in column.lowercased() == orderedColumn.lowercased() } What do you think? Seems like it would solve the type checker problem, uglify the code a lot less, and make the fixit/migration happily trivial.
Avatar
@norio_nomura
Sequence has an associated type Element that is equivalent to Iterator.Element. The value
of this associated type can be inferred from existing Sequence conformance. Code that already declares a type of Element may need to be altered to resolve conflicts. (32186094) https://bugs.swift.org/browse/SR-4951 に何も反応ないままこれとはw
Avatar
norio_nomura 6/6/2017 3:54 AM
まあ、予想はしてたw
3:56 AM
issueの元になったパッケージは、elementに変更してさらにSequence準拠もやめてました。
👍 1
Avatar
↓このスレッド、 SE-0110 以前(引数とタプルの区別)からひっくり返そうって言ってる・・・。 https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170605/037054.html
5:50 AM
As one of many who is directly affected and wants resolution, I think the discussion of re-evaluating SE-0110 most certainly expands to these earlier decisions. While Swift has moved in the direction of distinguishing tuples and argument lists in decidedly different ways, I think it's perfectly valid to consider the alternative: a simpler and equally-valid solution: flattened tuples that are isomorphic to argument lists.
Avatar
それ絡みで、 これは当然できないけど、 func foo(x: Int, y: String) { print(x) } foo(y: "foo", x: 12) これはできるんですよねー。 func foo(arg: (x: Int, y: String)) { print(arg.x) } foo(arg: (y: "foo", x: 12))
Avatar
@rintaro えっ、ラベル付きタプルって順番ひっくり返せるんですか?!
Avatar
omochimetaru 6/7/2017 6:24 AM
wwww
6:24 AM
そうだったのか。・・・
Avatar
↓できた。 let foo: (a: Int, b: String) = (b: "x", a: 42)
Avatar
...からの let (x: Int, y: String) = (y: "foo", x: 42) print(Int)
Avatar
let (x: Int, y: String) = 許されてるのバグじゃないかと思ってるんですけどどうなんでしょう?
6:28 AM
このラベル x, y が活きる場所がないし。
6:28 AM
いや、ちがうのか
6:28 AM
↑の順番入れ替えで活きてるのか。
6:28 AM
ヤバイ・・・
Avatar
タプルパターンにラベルが認められているのはこのためで、 let input = (y: "foo", x: 42) let (x: foo, y: bar) = input print(foo) これがやりたいから。
Avatar
omochimetaru 6/7/2017 6:28 AM
そのletの技めっちゃ混乱する
Avatar
で、誤って (x: Int, y: String) と書いた人が死亡するとw
6:29 AM
let (x, y): (Int, String) = としたい人が let (x: Int, y: String) = と書いて爆死するのが見えますねw
Avatar
@harlanhaskins @CodaFi_ We're pretty sure it was intended for tuple shuffles.
Avatar
omochimetaru 6/7/2017 6:30 AM
このツイートww
6:30 AM
High on iLife‏ @CodaFi_ 5月4日 その他 What do you mean Swift doesn’t have mixed-type arithmetic? let (x : Int, y : Double) = (3, 1) let result = Int + Double // 4
😂 1
6:31 AM
It would be great if we had some kind of community-driven process for cleaning up language edge cases like this
6:31 AM
Slava Pestov‏ @slava_pestov
6:31 AM
スラーバ氏、ツイッター担当みたいになってるな
6:31 AM
この手の話題によく反応してる
Avatar
そのくせにマッチングパターンではシャッフル出来ないとか、いろいろぐちゃぐちゃですね。 func foo(arg: (x: Int, y: String)) { switch arg { case (y: let bar, x: 0..<12): // error: tuple pattern element label 'y' must be 'x' break default: break } } (edited)
Avatar
ひどい・・・
Avatar
なんと、これは動く! func foo(arg: (x: Int, y: String)) { if case (y: let bar, x: 0..<12) = arg { print(bar) } } foo(arg: (x: 4, y: "test"))
Avatar
このへんって表面の見た目が同じだけで裏はぜんぜん違うものになってるんですかね
Avatar
えー、それどっちもパターンマッチなんじゃないのか・・・
6:40 AM
仕様として明確に決まってなくて、実装にブレで起こってそう
Avatar
omochimetaru 6/7/2017 6:40 AM
@t.ae コンパイラ実装のロジックという意味ではバラバラだろうね
6:41 AM
@rintaro if case = の形とswitch-caseで違うのは驚き
Avatar
完全にバグっぽいけど、現時点だとどっちの方向に直したらいいかわからないですねw
9:06 AM
Swift 4 では type(of:) は関数になったので、↓ができなくなった、と。 let type = 42 type(of: type) // Int
Avatar
続き 変数strideがあるときにstride(~)が昔は呼べてた気がするけどラムダのせいで呼べないなら昔も呼べなかったはずではないのか。 記憶が間違ってるのか。
Avatar
適切に type をシャドーイングできるようになったって話です。
Avatar
構文が関数の形式だったから、これは喜ばしい変更だと思う。
Avatar
昔はザルだった説
Avatar
ザルだった説と自分の記憶を信じたい
Avatar
変数strideがあるときにstride(~)が昔は呼べてた気がする
本当にそうだったかわからないけど、それ望ましくなくないかな?
(edited)
Avatar
Any はまだで、 Any という変数をつくることはできない。
Avatar
@koher 望ましくなかったけどできていた記憶があるというだけです。
Avatar
あー
Avatar
さすが rintaro さんはパーサー周りやってるだけあってそのあたりの闇に詳しいですね。
9:09 AM
↓はできた。 let Never = 42
9:11 AM
そういえば、 Never は当初から bottom type が想定されてたことをこの前知った。 https://github.com/apple/swift-evolution/blob/master/proposals/0102-noreturn-bottom-type.md#never-as-a-universal-bottom-subtype
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
9:11 AM
Never as a universal "bottom" subtype
Avatar
omochimetaru 6/8/2017 9:12 AM
おー
Avatar
enum Never {}なのもそれ意識した作りだと思ってた
9:13 AM
激しくデジャビュ、Twitterでやった記憶ある
Avatar
enum Never {} だとすべてのサブタイプになるのと整合性取れなくないですか?
Avatar
union型だと、無がNeverたり得るので、enumがそこへの拡張(或いは無名enumのようなunionがありえる?)とか諸々踏まえて
9:15 AM
case無しenumはまさに!という感じ
Avatar
例の func foo() == func foo() throws Never func foo() throws == func foo() throws Error と整合してる。 (edited)
9:17 AM
なるほどー。でも enum は tagged union であって untagged union じゃないから、サブタイピングが働かないのでやっぱ変な気が。
Avatar
まあそれはそうw
Avatar
でも、 Optional でサブタイピングになってると考えると、 Never も特別扱いもありかも?
Avatar
enumにサブタイピングサポート欲しいんですよね
Avatar
それは禁断の道では・・・
Avatar
それはそうか
9:19 AM
union欲しさのあまり定期的に気が狂ってしまう
Avatar
omochimetaru 6/8/2017 9:19 AM
www
Avatar
Optional の暗黙の型変換でもあれだけ嫌がってる @tarunon さんらしくないw
Avatar
Optionalの暗黙変換がいやなのは、なんか
9:20 AM
コンパイラが死ぬほど頑張って不完全で壊れやすいものを提供してるのが
9:20 AM
納得がいかない、言語仕様として定義して、その枠組みでやるならまぁ、という感じ
9:22 AM
というか!swiftはサブタイピング周りゆるゆるなので
Avatar
Ceylon に入信すると幸せになれるかもw https://ceylon-lang.org/documentation/1.3/tour/basics/ Foo?Foo|Null で、 TypeScript と違ってちゃんとした静的型付け言語。
Avatar
あぁ、やっと言語化できた
Avatar
Top Type が Anything で、その下に NullObject があって、 Bottom Type が Nothing でキレイです。
Avatar
swiftのOptional、機能的にも型的にも明らかにHaskellのMaybeじゃないですか。 なのに中途半端にunion Optionalに寄せるようなことしていて、
Avatar
ですよねー。 Tagged Union なのに Untagged Union っぽく振る舞わせるから混乱を招くんですよね。
Avatar
はー?クソって感じがしてる。言語機能でサブタイピング提供してサブタイピング周りガチツヨな言語になって、その上でMaybeとunion Optionalとが合体した最強の型
9:24 AM
そうなってくれるなら許しがあるし最高
Avatar
nil はいいとしても、 let a: Int? = 42 は禁止して let a: Int? = .some(42) を強制した方が色々問題起きなさそう。
9:26 AM
それか、これもシュガー用意して let a: Int? = 42? とか。
9:27 AM
言語機能でサブタイピング提供してサブタイピング周りガチツヨな言語になって、その上でMaybeとunion Optionalとが合体した最強の型 そうなってくれるなら許しがあるし最高 なるほど・・・。 (edited)
9:29 AM
でもなんか破綻しそうな気が・・・。
9:30 AM
union enum Foo<T> { case a(Int) case b(T) }
9:30 AM
Int|T として振る舞えるとして
9:30 AM
Foo<Foo<String>>Int|(Int|String) になっちゃうと
9:31 AM
Int|String と等価になってネストが消えちゃう・・・。
9:31 AM
もし、ネストが消えるのが union enum の正しい仕様だとすると、 Optionalunison にしたら、ネストできなくなってしまう。
Avatar
明示的に書けば可能だけど、書かなければ最適な位置に挿入される
Avatar
let a: Foo<Foo<String>> = 42 ってやると、 let a: Foo<Foo<String>> = .a(42) になるってことですか?
Avatar
はい
Avatar
let a: Foo<Foo<String>> = .b(.a(42)) ではなく。
Avatar
外側からのマッチングで振る舞って良さそう
9:35 AM
型的にはFoo<String>とIntがスーパータイプで、Foo<String>がStringとIntをスーパータイプに持ってる
9:35 AM
protocol oriented出来てるし、イケるのでは?と思ったけど
9:35 AM
思考漏れてそうだな
Avatar
↑(代入)だけなら暗黙の型変換ととらえることができるので、優先順位さえ決めれば一意に決められると思います。
9:37 AM
オーバーライドして戻り値狭めたり引数広めたりしたときにも問題ないかな・・・。
9:37 AM
あと、今は ArrayOptional でしかできないけど、 Covariant な型パラメータと組み合わせて問題ないか。
Avatar
あー、その辺protocolまだ動いてないんでしたね、そう言えば
Avatar
protocol 動いてないってどういうことですか?
Avatar
理論的には問題ない気がしています。実装が大変なのは容易に想像できますが
9:39 AM
A lot of people reported bugs in this area so it's worth mentioning that Swift now allows subclasses to override methods in a base class with a more general type.
9:40 AM
classとOptionalのサブタイピングをoveride出来るがprotocolは無理
9:40 AM
ここに理論的に障壁あるなら無理ぽ
Avatar
I'd like to show you my naive attempt to allow covariance in protocol conformance. I'm completely unsure if this is an acceptable solution, but it works 😅 Let me know what do you think of it? Resol...
Avatar
すごいアイコンw
Avatar
忙しいって書いてる、頑張って
Avatar
@koher また質問させてください🙏 protocol extension による継承が演算子を使った場合だけ思うように動作してないようで困ってます🙁 Gist を見て頂けると嬉しいです🙏 https://t.co/RMk6KZXCex
10:42 AM
これに変更を加えて色々試してたんだけど、 protocol extension とか関係なく演算子のときだけ関数やメソッドと挙動が違うっぽい。 https://gist.github.com/koher/e3886feed159599f184be5f6328ee5e1 (edited)
Avatar
protocol の requirement から func + はずすと意図した動きになりますね
Avatar
protocol×subclassだと宣言無しだと壊れてこっちは宣言有りだと壊れる?
11:27 AM
壊れる、というか、誓約ベースでGenericsを定義したが意図通りに動かない、か
11:27 AM
これ普通のfuncだと一見動いてるように見えるが、ライブラリが分かれるとダメ、とかあったはず。
Avatar
あれ?コメントアウトするの間違えてた💧
Avatar
swift4だとどれコメントアウトしても同じ動きっぽい
Avatar
norio_nomura 6/8/2017 11:45 AM
バグに見える
Avatar
@tarunon Addable+ をコメントアウトしても <Int> にならないってことですか?
Avatar
defaultですね
Avatar
より謎な方に倒れましたね・・・。
Avatar
norio_nomura 6/9/2017 3:26 AM
Swift 4で + コメントアウトで <Int> になるような
3:29 AM
protocol Addable { associatedtype SomeType func sayHello() static func sayHello2(_ x: Self) -> Self static func + (a: Self, b: Self) -> Self } extension Addable { func sayHello() { print("hello<default>") } static func sayHello2(_ x: Self) -> Self { print("hello<default>"); return x } static func + (a: Self, b: Self) -> Self { print("add<default>"); return a } } extension Addable where SomeType == Int { func sayHello() { print("hello<Int>") } static func sayHello2(_ x: Self) -> Self { print("hello<Int>"); return x } static func + (a: Self, b: Self) -> Self { print("add<Int>"); return a } } struct Concrete<T>: Addable { typealias SomeType = T } let a = Concrete<Int>() a.sayHello() // prints hello<Int> _ = Concrete.sayHello2(a) // prints hello<Int> _ = a + a // prints add<default> ... why? (edited)
3:32 AM
operator func だけ where が効いてない。 (edited)
Avatar
staticでextensionに入れてもダメなんですね
Avatar
norio_nomura 6/9/2017 3:33 AM
そう。条件を揃えてみました。
3:34 AM
operator funcだけprotocol requirementの有無で結果が変わる。
3:35 AM
Xcode 8.3.3とXcode 9 beta 1ともに同じ結果
Avatar
今やったらちゃんと変わった、なんだったんだろ
Avatar
この手のextensionでfunctionの動きを切り替えるの、動きそうで動かないこと結構あるし
5:41 AM
ライブラリ化したら大体意図通りに動かなくなるんでやらないほうが良い感ある
5:41 AM
operatorじゃなくっても上手く行かないことあります
Avatar
落としどころとしてはこんな感じでしょうかねぇ。 protocol Addable { func adding(_ other: Self) -> Self } func + <T : Addable>(lhs: T, rhs: T) -> T { return lhs.adding(rhs) } (edited)
👍 1
Avatar
protocol Animal { func bark() -> String } protocol Cat { } extension Animal { func bark() -> String { fatalError("abstract") } } extension Animal where Self: Cat { func bark() -> String { return "nyan" } } class AnimalImpl: Animal { } class CatImpl: AnimalImpl, Cat { } CatImpl().bark() // nyan 単一プロジェクトの中だと一見上手く動くんですが、CatImplが別ライブラリにあると上手く行かない。
Avatar
norio_nomura 6/9/2017 6:40 AM
アクセスコントロールは internal
Avatar
openで再現出来ます
6:41 AM
というかopenじゃないと、CatImplがAnimalImplのサブクラスに出来ない?
Avatar
norio_nomura 6/9/2017 7:08 AM
extension Animal where Self: Cat { func bark() -> String これがpublicならちゃんと動く。internalだとfatalError
7:14 AM
Avatar
7:14 AM
ありがとうございます!
Avatar
norio_nomura 6/9/2017 7:18 AM
operator funcの選択がprotocol requirement有無で変わるの、JIRAを探してもそれっぽいのは見つけられないな。
Avatar
@norio_nomura func testBark() { let cat: AnimalImpl = CatImpl() XCTAssertEqual(cat.bark(), "nyan") } (edited)
7:19 AM
これだと死ぬ
Avatar
norio_nomura 6/9/2017 7:20 AM
それは仕方ないのでは…
Avatar
そうなんですよね
7:20 AM
この辺の罠を踏みやすい、なるべく避けたほうが良いなぁという所感
7:21 AM
全てのクラス型の宣言がGenericsになってれば多分大丈夫なんですが、遥か遠い
Avatar
コンパイラのクラッシュ見つけたので再現しようとしたら意味不明な型を作ることに成功してしまった
7:31 AM
protocol A { } protocol B: Self.X { associatedtype X: A } class C: A { } class D: A, B { typealias X = C } D.X.self D.self D()
7:31 AM
これ通るの謎いw
Avatar
通ってます? こっちではクラッシュ Xcode9
Avatar
Xcode8で通ってます
7:33 AM
9だとクラッシュか
7:34 AM
protocol A { } protocol B: Self.X { associatedtype X: A } class C: A { } class D<Y: A>: A, B { typealias X = Y } extension String: A { } D<String>.self これでも通る、ヤバみ高いw (edited)
Avatar
omochimetaru 6/9/2017 7:34 AM
D.X = Cなのに、D is B だから D is C になってしまってるってこと?
Avatar
SwiftSandboxも通らないですね
Avatar
protocol B: Self.X
7:34 AM
この行がやばいw
Avatar
3.1.1なのでXcode8のみ?
Avatar
inheritance で Self 使えるのはやばいなw
Avatar
norio_nomura 6/9/2017 7:50 AM
そこにSelfを書こうとするのがやばいと思ったw
Avatar
なんか
7:52 AM
assoctypeにDelegateを置いて、functionの引数とか返り値でDelegateを使いつつ、自分自身もDelegateに適合していることを保証したかったんです。
Avatar
norio_nomura 6/9/2017 8:16 AM
すごいw
Avatar
ワンチャンあるかと思ったら盛大にぶっ壊れたw
Avatar
ちなみに master だとエラーでした。 test.swift:5:10: error: first type 'Self.X' in conformance requirement does not refer to a generic parameter or associated type protocol B: Self.X { ^ test.swift:5:10: error: inheritance from non-protocol type 'Self.X' protocol B: Self.X { ^ メッセージの意味がちょっと不明だけど。
Avatar
assoctypeは当然struct入れれるから、具体型を想定してるっぽい
Avatar
(...is constrained to be a subtype of another) Previously the compiler would just mark the entry in the inheritance clause invalid and move on without emitting any errors; in certain circumstances ...
Avatar
omochimetaru 6/10/2017 9:17 AM
@applideveloper 「APIのfetcherを使う時」というのがどういうコードなのか例がみたいです。僕は、推論を使いすぎると可読性が落ちるので適宜明示的な型宣言を書いたりはしますね。どのくらい明示的にするかは感覚ですが。推論自体は一般には計算量的には重くないです。しかし、一部に組み合わせ爆発するようなケースがあるので、そういうのをふむ場合は明示したほうが良いです。
Avatar
クロージャ毎にコンパイル時間計測できたっけ。出来るなら時間のかかる型推論がある場合にコードを記述する拡張機能とか作れないだろうか、と思ってる。
👍 1
Avatar
applideveloper 6/10/2017 12:36 PM
@omochimetaru さん、 同じ考えを持つ人がいて嬉しいです、僕が少数派かと思ったので、具体例は、以下のようなコードです。 https://github.com/applideveloper/VideoPlayer/blob/master/VideoPlayer/Model/Fetcher/VideoPlayListFetcher.swift#L36 (edited)
Contribute to VideoPlayer development by creating an account on GitHub.
Avatar
これはかなり遅いのではw
Avatar
「クロージャ」と言っているのは多分クロージャ式のことですよね?僕は↓の 3 段階くらいがあるように思います。 推測しやすいケース→ $0 等 推測しづらいケース→ わかりやすい引数名を付ける { image in ... }image の型は Image ) 名前からでも推測できないケース→型も書く { images: [String: Image] in ... }
Avatar
applideveloper 6/10/2017 12:49 PM
{ image in ... }これが、{ image: Image? in ... } の可能性もあるのでgit diffで確かめたくないんですよ、後ろの?でわかるんでいいんですが (edited)
12:49 PM
$0なら、いいんですが、{ images: [String: Image] in ... } 複雑で、右辺ですぐに推測できないを省略するのは好きじゃないです (edited)
Avatar
Image? の場合は { image: Image? in ... } とするルールじゃダメですか? git diff で、というのはどういうことでしょう?
Avatar
applideveloper 6/10/2017 12:51 PM
{ (response: Response<[Video], NSError>) in } { response in } (edited)
12:51 PM
レビューする時です。書くのは一回で済むのですが、読むのはなんども読むので読み手にコストをかけたくないんですよ (edited)
Avatar
それはチームでわかりやすいコーディング規約を決めて、それを守るのがいいと思います。
12:54 PM
array.map { $0 * $0} みたいなケースまで型を記述するのはナンセンスですし、どこかにラインを定める必要がありそうですね。
12:55 PM
ちなみに、 Xcode だったら Option + クリックで型を確かめられますよ。
12:55 PM
GitHub 上だとどうしようもないですが。
Avatar
applideveloper 6/10/2017 12:56 PM
開発を止めて、git checkout させて、Option + クリックさせるのを読み手に払わせるんのがコストなんですよ (edited)
Avatar
ちゃんとレビューするならビルドは通してと思わなくもない
Avatar
本格的にレビューするときは変数や型、メソッドの定義元に飛べないと効率が悪いので checkout してからレビューする方が良いように思います。
Avatar
self.hogehoge の self の省略とかも、IDEなら色分けされるけどただのsyntax highlightだとされないとかあるし
12:58 PM
さっきの .responseArray { (response: Response<[Video], NSError>) in とかは僕も型を書きたい部分です
Avatar
さっきの .responseArray { (response: Response<[Video], NSError>) in とかは僕も型を書きたい部分です
これは僕も同意です。こういう推測不能なものは型を書いた方がいいと思います。
Avatar
これに関して言うと、SwiftTaskがPromiseリスペクトなので型推論が遅い、と言うのはありそう
1:00 PM
SwiftTaskのinitにクロージャを渡してるところから型を書いた方が良いですね (edited)
Avatar
applideveloper 6/10/2017 1:00 PM
型推論でどのぐらい遅くなるかってのを説明できれば、推測不能なものは型を書いてくれるようになるのかなと (edited)
Avatar
omochimetaru 6/10/2017 1:00 PM
case Result<[Video], NSError>.Success(let videoArray): ここは case .Success(let videoArray): にしたいけど。
Avatar
applideveloper 6/10/2017 1:01 PM
.responseArray { (response: Response<[Video], NSError>) in これを書いていたら case .Success(let videoArray): これの型が人間が推測できるので、省略しても問題ないと思います。 (edited)
Avatar
omochimetaru 6/10/2017 1:02 PM
はい、そうおもいます
Avatar
関数毎にコンパイル時間計測して、一定時間以上かかると警告出るフラグがあるので
1:04 PM
それ入れて警告出たら型書け、と言うのが良さそう
Avatar
applideveloper 6/10/2017 1:06 PM
例えば、極端な例で、型書くのが1秒で、 型書かないで、毎回のコンパイルで型推論に1秒かかるなら、 どちらを選びますかってなるんですよ (edited)
Avatar
Other Swift flagsに -Xfrontend -warn-long-function-bodies=1000 ↑を入れれば警告出るようになります
👍 1
1:08 PM
そこは単純に決めの問題で、1000はミリ秒ですね。
1:08 PM
警告出たら書く、は非常に分かり易い指標なので、導入も楽だと思いますよ
Avatar
マシンスペックによってチーム内でブレが出そう・・・
1:09 PM
まあ、組み合わせ爆発で極端に遅いかそうでないかのケースが多いから、うまいしきい値を設定すれば問題ないかな?
Avatar
低いマシンスペックの人がどんどん気付かずに不幸になっていくよりは、低いマシンスペックの人が自分で気づけてPR投げれるので
1:10 PM
まだ幸せだと思います
Avatar
なるほど。
Avatar
applideveloper 6/10/2017 1:10 PM
僕が言っても聞いてくれないので、その辺り発言力がある人が記事を書いてくれると嬉しいなぁ (edited)
Avatar
悲しい…
Avatar
applideveloper 6/10/2017 1:12 PM
コンパイル時間を奪うならまだいいのですが、 推測不能なケースで、書くのは1秒なのですが、毎回読むたびに1秒以上人間に推測や、調べさせるのは好きじゃないです。 (edited)
Avatar
個人的にはもはやGithubだけでレビューは、レビュー自体の信頼に関わるレベルでやるべきでないと思っていて
Avatar
推測不能なケースはもちろん書くべきだと思うのですが、それが当然だと受け止められない環境だということですか?
Avatar
applideveloper 6/10/2017 1:15 PM
そうですね(>_<)
Avatar
それは辛いですね・・・
Avatar
2,3行変更しました、以外はチェックアウトして一回ビルドするようにしてる。
1:16 PM
とりあえずコンパイル時間遅いのはどうでも良くなくって、これ日々の開発効率に直結してるんで
1:16 PM
往々にして推論が遅いコードは人間が読むのも大変なので、その方向で修正していければ良いかなぁ。
Avatar
applideveloper 6/10/2017 1:17 PM
そうするのですが、iOSのビルドって時間かかるので、早くしたいのですよ
Avatar
以前、僕が1関数で1分コンパイルに時間がかかってしまう化物を生み出してしまって、その結果さっきのコンパイル時間で警告出すフローを導入するに至りました。
👍 2
1:20 PM
10分ぐらいコンパイル時間かかる爆弾を埋め込んで、チーム全体をコンパイル時間改善しようというムードに持っていくのはどうだろう
Avatar
10分ぐらいかかる爆弾、作るのも大変そう(昼間にコンパイル時間かかる爆弾うっかり作ってしまったらコンパイラに複雑すぎると仕事を放棄されてしまった)
Avatar
確かに作るの難しいですね
Avatar
その人たちの上に掛け合って自分でコーディング規約用意して推進しちゃうとかですかね🤔
Avatar
applideveloper 6/10/2017 1:24 PM
その規約が間違ってた場合どうしたいいですかね? (edited)
Avatar
現場において規約が間違うって合意形成の問題だと思っていて、ベースとして有名な規約を選んで現場に合わせてカスタムすればそんなには揉めないと思います
1:27 PM
議論するコストを抑えるためのルール作りって話しなので
1:29 PM
大体のSwiftのコーディング規約はclosureの型は明示的に書こうってなってた気がする
Avatar
applideveloper 6/10/2017 1:30 PM
有名な規約にそってない場合はどうしたいいですかね?チームの多数決で負けている、というか僕一人 (edited)
Avatar
そこはぶつかってみるしかないのかなーと思います、相手の言い分も取り入れつつ完全に言い負かすとかしないで、限定的にこの場合は無名変数OKとか
1:35 PM
気にしてるのが1人なのであれば尚更主導で引っ張る気持ちで、メリットを伝えてお願いするのが良いかと
1:37 PM
それでも無理なら...(ry
Avatar
applideveloper 6/10/2017 1:37 PM
ぶつかって負けたけど、計測して訴えたいと思います
👍 1
Avatar
(ryの先が気になる、転ですかね
😇 2
Avatar
applideveloper 6/10/2017 1:42 PM
負けたとき一瞬考えましたw (edited)
Avatar
他人を変えるエネルギーより自分の環境を変えるほうが圧倒的に楽ですねw
Avatar
applideveloper 6/10/2017 1:55 PM
型推論でどれだけ遅くなるかの事例集のデータって需要ありそう
Avatar
omochimetaru 6/10/2017 1:55 PM
これいいな Other Swift flagsに -Xfrontend -warn-long-function-bodies=1000 ↑を入れれば警告出るようになります
Avatar
だいたいflatMapが遅い
1:57 PM
クロージャの返り値がジェネリクスで定義されたプロトコルに準拠していてかつ、式全体の型は左辺によって決定している、みたいなの
1:57 PM
要するにこれflatMapなんですが、これがメソッドチェインすると爆発します
👍 2
Avatar
flatMapのチェインは良くやるので、やらかしてそう
Avatar
omochimetaru 6/10/2017 2:01 PM
個人的にはもはやGithubだけでレビューは、レビュー自体の信頼に関わるレベルでやるべきでないと思っていて
2:02 PM
本格的にレビューするときは変数や型、メソッドの定義元に飛べないと効率が悪いので checkout してからレビューする方が良いように思います。
2:02 PM
ここらへん同意がある
2:02 PM
githubだと型定義に飛べないので、ブラウザを操作している時間を積み上げていくと
2:03 PM
checkoutする手間を上回るように思う
2:04 PM
型を書く1秒をケチったことで、積み上がっていく型を読み解く1秒の積み重ねで赤字になるのと同じ発想
Avatar
applideveloper 6/10/2017 2:05 PM
checkoutはしますが、そのビルドが遅くなるのと、調べる必要がないInt,Int?型とか覚えてる型だったら書いて欲しい、Doubleなのかとかで時間を奪われたくない (edited)
Avatar
自分は作業用とレビュー用で分けてcloneしてきて、両方ビルド回しちゃってます
Avatar
omochimetaru 6/10/2017 2:07 PM
あー
2:08 PM
それ良さそうですね
Avatar
マシン分けたい
Avatar
omochimetaru 6/10/2017 2:09 PM
なるほど
Avatar
wantedlyとかは1人2台でそういう体制とってるってどこかで記事見ましたね
Avatar
つよそう
Avatar
omochimetaru 6/10/2017 2:10 PM
新マシン届いたら旧と並べて試してみよ
2:10 PM
speee社はビルド用のimacとmbpの基本2台体制らしいで
Avatar
applideveloper 6/10/2017 2:11 PM
うらやましい
Avatar
github の プルリクエスト の ブランチ チェックアウトが Xcode に 組み込まれたらいいのにな。
Avatar
applideveloper 6/10/2017 2:14 PM
人間がすぐに推測できない不適切なケースでの型の省略って、相手の時間を奪ってるっていう認識がないと思うんですよね
Avatar
fork先のブランチチェックアウトほしいですね
Avatar
omochimetaru 6/10/2017 2:15 PM
「人間がすぐに推測できない」ラインの感覚のズレの問題なのか
2:15 PM
とにかく推論させられるだけさせたい、っていう根本的な考え方の違いなのか?
2:16 PM
「リーディングに時間がかかる」っていう問題意識自体はわりと賛同されやすいと思うんですけどねえ
Avatar
norio_nomura 6/10/2017 2:18 PM
PRブランチ取得はこれ使うとremote足さなくて済む。 https://gist.github.com/piscisaureus/3342247
Checkout github pull requests locally
👀 2
2:21 PM
XcodeのSource Controlはチェックアウト時にサブモジュールを取得してくれないので使えない。
Avatar
hubコマンドを使うと git checkout https://github.com/.../.../pulls/1みたいな感じでcheckoutできたはず
Avatar
omochimetaru 6/10/2017 2:23 PM
ほ〜
2:23 PM
git configのorigin/fetchがそもそも
2:23 PM
マッチングパターンで書けるから
2:23 PM
PRブランチに規約切っとけばそういうことができるのか
2:23 PM
あ、いや、ちがうな
2:24 PM
これはfetchコマンドの対象を追加してるだけか
Avatar
norio_nomura 6/10/2017 2:24 PM
GitHubさんが融通してくれるのです。
Avatar
omochimetaru 6/10/2017 2:24 PM
なるほど。gitだけの仕組みだとどうなってんだと思った。
Avatar
norio_nomura 6/10/2017 2:25 PM
/head の代わりに /merge を使うとマージコミットも作ってくれるのだったかな?
Avatar
https://hub.github.com/ 知らなかっただす。ありがとございます!
😀 1
Avatar
applideveloper 6/10/2017 2:27 PM
http://qiita.com/kaneshin/items/1deebde685c973fda6b8 これプロジェクト名.pbxprojのコンフリクトを直してくれるので便利ですよ brew install mergepbx (edited)
Avatar
いっつも ref名わすれて、 https://help.github.com/articles/checking-out-pull-requests-locally/ 行ってた。
Avatar
norio_nomura 6/10/2017 2:45 PM
if let convertibleType = type.self as? IntConvertible.Type { という書き方を知った。 import Foundation protocol IntConvertible { static func convert(from int: Int) -> Self? } extension Int { func convert<T>(to type: T.Type) -> T? { if let convertibleType = type.self as? IntConvertible.Type { return convertibleType.convert(from: self) as? T } return nil } } extension Date: IntConvertible { static func convert(from int: Int) -> Date? { return Date.init(timeIntervalSinceReferenceDate: TimeInterval(int)) } } 1.convert(to: Date.self) // "2001/01/01 9:00"
Avatar
assoctypeだと出来なくて憤死するやつ
Avatar
norio_nomura 6/10/2017 2:46 PM
そそ
Avatar
これって、type-erasureが要らなくなった未来のswiftでも多分出来ないままですよね
2:47 PM
どうなるんだろ、構文的な解決も難しそうだし
2:52 PM
if let seqType = T.Type as? Any<Sequence where .Element==Int>.Type とか? (edited)
2:56 PM
特に書いてないけど出来るようになる…のかな
Avatar
norio_nomura 6/10/2017 3:03 PM
遠そう…
Avatar
https://swift.org が落ちてる?
🤔 1
Avatar
復旧してた
Avatar
はじめまして Codableに準拠したクラス/モデルが、Optional<URL>のプロパティを持つときにdecodeできないのですが、どなたか既に試された方はいらっしゃいますでしょうか? 詳しい情報とテスト用のplaygroundをgistにあげておきます。 https://gist.github.com/ken0nek/4a84f5fb1d13e4201907ddcdcccc3cf1 お助けいただけますと幸いです。
Can not encode/decode an entity which has Optional property.
Avatar
25行目の、try container.encode(ou, forKey: .ou) decode側がdecodeIfPresentなのでこちらもencodeIfPresentにするべき?
Avatar
動きました、、 ありがとうございます、、!
Avatar
というかOptional<Codable>Codableじゃないのかな…
Avatar
試してみましたが、いまのところダメでした (edited)
Avatar
オッ
10:48 AM
じゃあそのうち追加されますね
10:48 AM
やった
Avatar
Conditonal Conformanceがないのでランタイムチェックだけどこういう感じですね
Avatar
@tarunon @ikesyo ご丁寧な対応ありがとうございました
Avatar
Conditional Conformance ってずいぶん前の Proposal だったからすっかり実装済みな気分になってましたがまだだったんですね・・・。
Avatar
この間ConditionalConformanceのためのコードを書こうとして寝落ちして放置してたんですが、寝て正解でした。
😅 1
Avatar
OptionalならdecodeIfPresentじゃなくてdecodeでよさそうな?OptionalのdecodeIfPresentの場合は戻り値の型がT??になるから型が合ってなさそう(上の画像)
Avatar
OptionalならdecodeIfPresentを使ったほうがいいのかと思っていました、、
Avatar
typeがURL?.selfだと正常値がURL?で、decodeIfPrsent使うとキーがない場合そのOptionalとしてURL??として表現されますよね。 (edited)
11:07 AM
URL.selfを使うのが文脈的に正しい
Avatar
Optional<Codable>: Codableになってない今の状況だと、try values.decode(URL.self, ...)がOptional<URL>に代入可能、っていうのが少しむずかしいかもしれない
11:09 AM
ifPresentはキーの有無があり得る場合のため、ですね
Avatar
そうですね、キーがあってそこから変換に失敗する場合は普通にエラーになる
11:10 AM
そのケースでも失敗にせずnilになってほしいなら
11:10 AM
decodeをtry?で使う感じになるかな
Avatar
try? values.decode(URL.self, forKey: .url) ?? nil
11:11 AM
って感じですかね
Avatar
将来的にdecode(URL?.self, forKey:...) が通るようになれば、誤解は減りそう
Avatar
今それで通るのでは?
Avatar
@Ken init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) self.ou = try values.decode(URL.self, forKey: .ou) self.u = try values.decode(URL.self, forKey: .u) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(ou, forKey: .ou) try container.encode(u, forKey: .u) }
11:11 AM
これでOKです
11:12 AM
今はまだ、URL?がCodableじゃないって怒られますね
Avatar
Optional: EncodableとOptional: Decodableなのになぜ……
11:13 AM
結構乱暴なことしてますねw
Avatar
ランタイムチェックとはそういうことですw
11:14 AM
WrappedがEncodable/Decodableじゃなかったらランタイムエラー
Avatar
なるほど
Avatar
この作りなら自動導出のでいけそうに見えるんだけどな
11:16 AM
Array/Dictionaryも同じことに今なってるっぽいです < ランタイムチェック (edited)
Avatar
Himotokiよろしく、Array,Dictionary,Optionalをオーバーロードするなりして、通してるのかと想像してた
Avatar
自動でいけますね。
Avatar
encodeで try container.encode(u, forKey: .u)u = "https://www.apple.com";try container.encode(ou, forKey: .ou)ou = { relative = "https://www.apple.com"; }; だけど try container.encodeIfPresent(ou, forKey: .ou) だと ou = "https://www.apple.com"; になるの、なんだか気持ち悪い気がしました
12:42 PM
swift - The Swift Programming Language
Avatar
norio_nomura 6/12/2017 1:03 PM
僕が書いてるYamsのYAMLEncoderだと ou: relative: https://www.apple.com u: relative: https://www.apple.com で、どっちも辞書型になる。 (edited)
1:04 PM
JSONEncoderURLを文字列としてエンコードする様に特別扱いして、URLCodable実装を迂回してる。 https://github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/JSONEncoder.swift#L691
swift - The Swift Programming Language
1:05 PM
デコード時にもURLCodable実装を迂回する様にしないと、上手くいかないはず。 (edited)
Avatar
norio_nomura 6/12/2017 1:25 PM
エンコードでOptional<URL>を特別扱いできていないのに、デコードでURLを特別扱いしようとして失敗する感じか。
Avatar
なるほどそんなところで特別扱いが
Avatar
norio_nomura 6/12/2017 2:23 PM
シリアライズ先でサポートされているデータ型の場合、Swiftの型のCodable実装ではなく、シリアライザがそれらを特別扱いしないといけない場合があります。
2:26 PM
例えば、Date.encode(to:)は自身をDoubleとしてシリアライズしてしまいますが、シリアライズ先に日付型がある場合それでは不適当。 (edited)
Avatar
norio_nomura 6/12/2017 2:56 PM
Optional<URL>を特別扱いできていないのは、extension Optional: Encodableの実装 https://github.com/apple/swift/blob/890c2d50159892e5160481c6882e10a2fc75e249/stdlib/public/core/Codable.swift#L3249 で直接ラップされた型のencode(to:)を呼んでるから。 var container = encoder.singleValueContainer() switch self { case .none: try container.encodeNil() case .some(let wrapped): try (wrapped as! Encodable).encode(to: encoder) }
swift - The Swift Programming Language
Avatar
URLに加えてURL?を特別扱いしないといけなかった、ということですかね
Avatar
norio_nomura 6/12/2017 2:57 PM
しかしコレ、try container.encode(wrapped as! Encodable) ができないな。
Avatar
自動導出のだとURL?でもstring直接でencodeされたのもちょっと気になる
Avatar
norio_nomura 6/12/2017 3:04 PM
コンパイラは try container.encodeIfPresent(url, forKey: .url) というコード生成するぽい。
3:04 PM
それだと Optional<URL> でも特別版を呼ぶ。
3:09 PM
GitHub is where people build software. More than 22 million people use GitHub to discover, fork, and contribute to over 60 million projects.
3:12 PM
URLに加えてURL?を特別扱いしないといけなかった、ということですかね
Encoderの特別版が呼ばれる様に、containerencode(to:)を呼ばないといけないですね。
Avatar
Optional:Encodableとするなら、IfPresentで特別扱いするというのは直感に反してる気がするなぁ
3:13 PM
eocodeで特別扱い出来て欲しい
Avatar
norio_nomura 6/12/2017 3:17 PM
protocol P {} func f<T: P>(_ p: T) {} let int = 0 f(int as! P) // error: cannot invoke 'f' with an argument list of type '(P)' ぬうう (edited)
3:18 PM
protocol P {} func f<T: P>(_ p: T) {} func f2(_ any: Any) { if let p = any as? P { f(p) // error: cannot invoke 'f' with an argument list of type '(P)' } }
Avatar
func cast<T>(_arg:Any)->T使えばいけそう
3:21 PM
あーーー
3:21 PM
AnyP的なのにしないと
3:21 PM
Genericsが具体型を知れないからコンパイル通らない
Avatar
ResultのAnyErrorと同じパターンかな
Avatar
norio_nomura 6/12/2017 3:23 PM
Containerたちのfunc encode<T : Encodable>(_ value: T…) throws達はジェネリックじゃない方が良かったのかな…
3:23 PM
DecodableEncodableassociatedtype無いし。
Avatar
厳しさを感じる
Avatar
self.ou = try values.decode(URL?.self, forKey: .ou) 今試したらこれは通ってた
3:30 PM
@norio_nomura try container.encode(wrapped as! Encodable)これなんですが
3:30 PM
Conditional Conformance入れば多分必要無くなるはずで
3:30 PM
そこまで大きな問題では無さそう。
Avatar
norio_nomura 6/12/2017 3:31 PM
Swift 4に入るのですかね…
Avatar
入らない可能性がある…
Avatar
もし入れば確かにwrappedそのまま渡せるから問題なさそう……
Avatar
そして現状でもOptional<Any>になってるようなことはなく、Wrapped型ははじめからCodable準拠な気がしていて
3:33 PM
あー
3:33 PM
JSONEncoderの実装側が困るのか
Avatar
funcの中でtypealias EncodableWrapped = Wrapped & Encodableとかしてその型にキャストとかという無茶できないかな
Avatar
norio_nomura 6/12/2017 3:37 PM
Wrapped & Encodableerror: non-protocol, non-class type 'Wrapped' cannot be used within a protocol-constrained type になります。
Avatar
そっか無理ですね
Avatar
let encodableType = Wrapped.self as? Encodable.Type (edited)
3:40 PM
とか?
Avatar
norio_nomura 6/12/2017 3:45 PM
キャストではダメぽい。
3:46 PM
AnyEncodableを作らないといけないとすると、かなりイケてない…
Avatar
AnyEncodable無し出いける方法が無い…
4:03 PM
extension Optional where Wrapped: Encodable { public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { case .none: try container.encodeNil() case .some(let wrapped): try container.encode(wrapped) } } } extension Optional { public func encode(to encoder: Encoder) throws { fatalError() } } これはダメでしたっけ
4:04 PM
ダメだった気がする
Avatar
先日のprotocol requirementsがあるoperator funcの解決順がおかしい件、登録されてなかったらしようと検索したら、inamiyさんが登録してくれてた。 https://bugs.swift.org/browse/SR-5181
Avatar
AnyEncodableを作らないといけないとすると、かなりイケてない…
AnyEncodableを作って呼び出せたとしても、Container側でAnyEncodableの中身をチェックして特別扱いが必要な型かどうかチェックしないといけなくなる。
(edited)
😱 1
12:34 AM
どうせランタイムで型チェックが必要ならば、やっぱりContainer.encode(_:…)はジェネリックじゃない方が良い気がする。 (edited)
Avatar
ですねぇ、Genericsに出来るのはConditionalConformが必要だ
Avatar
norio_nomura 6/13/2017 1:22 AM
とりあえずissue登録した。 https://bugs.swift.org/browse/SR-5206
Avatar
norio_nomura 6/13/2017 1:32 AM
コンパイラが生成するのと同じCodable実装をXcodeが生成してくれると間違いが減りそう。
Avatar
omochimetaru 6/14/2017 1:41 AM
extension String: Error {} ってなんかやばめな香りがするんだけど何が悪いのかは説明できない
1:41 AM
何でもthrowできるのはなぜ良くないのかも僕は説明できなそう 便利やんを論破できない
1:42 AM
どうなんだ
Avatar
catchするときに型に準拠したパターンマッチできないから弱いのと、パラメータ持たせられなくてErrorがprotocolである良さみを殺している
1:45 AM
恐らくこれをやると、大域変数にErrorを示すがError以外にも転用可能なString変数、と言うのが出現するので、まあNotification.Nameみたいに、RawRepresentableで具体型作って、それをError準拠させましょうね、というところが落としどころではありそう。
1:46 AM
少なくともErrorの変数がStringとしても使える状況は良くない。
Avatar
omochimetaru 6/14/2017 1:47 AM
catchするときに型に準拠したパターンマッチできない
これは他のHogeErrorでも同じじゃない?
パラメータ持たせられなくて
文字列1個だけ持たせるErrorだったら等価じゃない?
1:47 AM
大域変数にErrorを示すがError以外にも転用可能なString変数
文脈的にエラーじゃない場合もあるのにそれがエラーとして取り回されてるとニュアンスが曖昧になるっていうのは確かに問題だ
1:47 AM
普通 HogeError って型は絶対にエラー(失敗情報)を示すデータだもんね
1:48 AM
少なくともErrorの変数がStringとしても使える状況
これは逆じゃない? String が Error として使えるんでしょ
Avatar
いや、それがErrorのための変数がStringになってる、と言う状況を生むからダメ
1:49 AM
まあレギュレーション違反をコンパイラが見つけれるようにしておこうね、という話につきると思う
Avatar
omochimetaru 6/14/2017 1:49 AM
なるほど
Avatar
Errorのための変数がStringになってる、と言う状況を生むからダメ
納の得した
👍 1
Avatar
omochimetaru 6/14/2017 2:00 AM
納の得 ってなんて読むんだ
Avatar
発音不能っぽい
Avatar
omochimetaru 6/14/2017 2:00 AM
ナツで変換できねえ
Avatar
最the高みたいなもんだから考えなくてよし
Avatar
omochimetaru 6/14/2017 2:00 AM
それは「サイザコウ」でしょ
Avatar
おもち君、発音できないと気になるタイプだった
Avatar
omochimetaru 6/14/2017 2:01 AM
そうだった
Avatar
初音ミクかよ
Avatar
おもちミク
Avatar
omochimetaru 6/14/2017 2:01 AM
N A T T O K U SPACE LEFT N O , って打鍵してんのかしら
Avatar
YES
Avatar
omochimetaru 6/14/2017 2:01 AM
納の得
Avatar
そこそんなに掘り下げると思ってなかったけど全然なんも考えてないよw
Avatar
omochimetaru 6/14/2017 2:02 AM
ちょっとおもしろかったんで気になった
Avatar
寒すぎてSome<T>のほうが面白いよ
🌨 1
🤣 1
Avatar
>コンパイラが生成するのと同じCodable実装をXcodeが生成してくれると間違いが減りそう。 Source Editor Extensionでいけそうな匂いしますね
4:54 AM
CodingKeyが必要になったときに自前で書くのダルいので早めに作られてほしさある
Avatar
Source Editor Extension
これって、各々作れる感じなんですか?
6:21 AM
あとで試してみよう
Avatar
現在のソースファイル内しか編集できない(ファイルを跨げない)という制約あるんですが、CodingKeyならそれで問題ないですよね
6:25 AM
tib/awesome-xcode-extensions: Awesome native Xcode extensions. https://github.com/tib/awesome-xcode-extensions なおサンプルはここらへん辿れば参考になりそう
awesome-xcode-extensions - Awesome native Xcode extensions.
Avatar
そうすると型推論の遅い型を追記してくれるエクステンションは作れないか…
Avatar
厳しそう…。
Avatar
norio_nomura 6/14/2017 7:59 AM
Xcode 9でSource Editor Extensionは何か変わったのかな?まだチェックできてないや。
8:02 AM
とりあえずhttp://bugreport.apple.com へはフィードバック済み。>Codable実装コードの生成機能がXcodeに欲しい (edited)
✨ 1
Avatar
What's new in Xcode 的なセッションはありませんでしたねー
8:11 AM
期待してたんですけど
Avatar
Xcode 9 beta 1の変更が http://github.com/apple/swift に来た。
swift - The Swift Programming Language
Avatar
↓のコメント書きながら改めて感じたけど、 Swift が Logic failure と -Ounchecked を裏表にしてるのほんとよく出来てる。 http://qiita.com/HaNoHito/items/841e9bd112ae6cb1c9a7#comment-337a4de3d810dbcc2e43 (edited)

概要

Swiftには、オーバーフロー演算(&+, &-, &*)と呼ばれる演算がある。 オーバーフロー演算を使用することで、オーバーフローの判定とエラー処理が行わずに演算を行うことができる。 その結果として、通常の演...
Avatar
omochimetaru 6/15/2017 2:33 AM
高速化のために &+ を使うシナリオにおいては、オーバーフローに伴うバグが排除されている事が検査済みであると仮定できるはずであるから、 -Ouncheked を使う事によって、 + を高速化すれば良い って論理ですかね?
2:35 AM
「オーバーフローに伴うバグ」と「-Ouncheked でチェックが除去されるバグ」の範囲が一致していないから、微妙に論理が間違っている気がする。
2:35 AM
オーバーフロー演算子に関してだけ、 -Ounchecked にする、みたいな、コンパイラオプションが有ると理想的だ
Avatar
もし Forced unwrapping や Arraysubscript の範囲チェックは残したいけどオーバーフッローのチェックだけ無効化したい場合は、その部分だけを切り出してコンパイル単位を変えるのがいいんじゃないかな。
🙂 1
Avatar
norio_nomura 6/15/2017 3:43 AM
Rustみたいに複雑なことまで望まないけど、共通のジェネリックメソッドシグネチャで受け取れるけど実装は型に特化したものを複数作れる、みたいなの欲しいな。
Avatar
お、最近話題の↓にも言及されてる。 let (a : Int, b : Float) = foo()
5:18 AM
これなくすって言ってるけど、この前の @rintaro さんが言ってた↓はできなくなっちゃうのか。 let (a: x, b: y) = (b: 3, a: 2) // x: Int = 2 // y: Int = 3
5:19 AM
なぜか僕に振られたので整理したのですが、
5:20 AM
CodaFi_ がプロポーザル出している通り、無くしていこうぜっていう方向なんだと思います。
Avatar
すごい、こういうの得意な人として認知されてる・・・
5:22 AM
↑ができなくなってもややこしさを解消できるメリットの方が大きそうですね。
Avatar
https://bugs.swift.org/browse/SR-5162 この件もありますしねー
Avatar
Discussion was leaning towards allowing (at least) the parenthesized form, but more discussion is needed. これは、 dict.forEach { ((k, v)) in ... } をできるようにするってこと?
Avatar
dict.forEach { (k, v) in ... } それかこっちですね。けどこれだと、どうrationalizeするのか分からないです。
Avatar
それだと曖昧性残っちゃいますもんねぇ。でも for だと for (k, v) in dict { ... } って書けるのに、クロージャ式では ((k, v)) になるのも微妙ですね・・・。
Avatar
クロージャーのコンテキストタイプが一つの引数しか取らないときに、クロージャが { (なにか) in だったら、パターンとして扱う。というルールで解決できるのかな?
5:37 AM
dict.forEach { (k: Int, v: String) in ... } でおかしな事になりますね。
5:38 AM
だから let (a : Int, b : Float) = foo() これの話が出てきたのかも。
Avatar
ですねぇ。
5:39 AM
やっぱり 1 引数 1 戻り値モデルを崩したあたりに無理があったのかなぁ・・・。
Avatar
Slava の恨み節が泣けてくるw https://twitter.com/slava_pestov/status/875150641269571584
My next language will avoid all of these problems by not having function arguments. Or functions, or values
Avatar
関数の引数のないwすごいw
Avatar
個人的には可変長引数は廃止でもいいけど、 inout とか @autoclosure とか考えると 1 引数 1 戻り値モデルはきついのかなぁ。
5:47 AM
別に inout@autoclosure が型の一部を成せばいいだけ?
5:48 AM
inout がキーワードなのに @autoclosure が attribute なのも違和感を感じる。
Avatar
タプルパターンのラベルを無くすのと、シャッフルを無くすのは別の話にできるということに気づいた。 let (foo, bar) : (y: String, x: Int) = (x: 12, y: "test")
Avatar
なるほどー。
6:20 AM
関数型の引数にはラベル付けられなくなったのに、タプル型だとラベル付けられるのも気持ち悪い気も。
6:20 AM
関数の引数がタプルでなくなったとはいえ、イメージ的にも見た目的にも似たものが異なる挙動をするというのはややこしい・・・。
Avatar
可変長引数がないと、ArrayとかDictionaryのリテラルが使えなくなる気がする (edited)
Avatar
可変長で受けるのも Array で受けるのも同じじゃないですか?(リテラルについて) (edited)
Avatar
[1,2,3]この表現が、可変長引数の関数を呼んでたような
Avatar
omochimetaru 6/16/2017 3:40 AM
appendの3重呼び出しになればいいのでは
Avatar
ExpressibleByArrayLiteralinit の引数が可変長じゃなくて Array になれば良くないですか?
Avatar
ExpressibleByArrayLiteralですね
Avatar
いや、[1,2,3]これがArrayをinitするために可変長引数が必要なので、
3:42 AM
appendを三回呼ぶにしても要素を可変長で解釈できる仕組みがいる
Avatar
でも可変長引数の実体は Array だから、どこかで Array が組み立てられてるんじゃないですか? (edited)
Avatar
omochimetaru 6/16/2017 3:42 AM
MakeArray(1) => { $0.Append(2) } => { $0.Append(3) }
Avatar
コンパイラが生成する中間コードだけ可変長引数サポートというのは逃げ道かも知れない
Avatar
可変長引数に渡すときに作られる Array は _allocateUninitializedArray っていう関数で作られているようです。 https://github.com/apple/swift/blob/master/stdlib/public/core/Arrays.swift.gyb#L985-L1009
swift - The Swift Programming Language
Avatar
https://github.com/apple/swift/blob/master/stdlib/public/core/Arrays.swift.gyb#L942-L960 ここからどうやって_allocateUninitializedArrayに繋がるのか追えなかった…(´・ω・`)
swift - The Swift Programming Language
Avatar
-emit-sil で見ただけです。たぶん String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) (https://github.com/apple/swift/blob/master/stdlib/public/core/String.swift#L726-L729) みたいなものですね。 (edited)
swift - The Swift Programming Language
6:16 AM
可変長引数に渡す前に caller 側で呼ばれて、要素のイニシャライズまでされるので、 init(arrayLiteral:) の前段階になります。
Avatar
omochimetaru 6/16/2017 7:12 AM
たとえ fatalError だけ代わりの方法で対処できたとしても、その他の Universal Error (メモリが足りないとかスタックオーバーフローとか)は起こりうるので、結局それらが発生したっ場合のログは送れないですし。
Swift could support a secondary, untyped propagation mechanism using "zero-cost" exceptions. ... However, this work is outside of the scope of Swift 2.0. https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst#universal-errors とあり、将来的にサポートされる可能性もあるかと。
swift - The Swift Programming Language
7:12 AM
fatalErrorのキャッチみたいな事ができるようになっても秩序は保てるのか
7:12 AM
> koher - 今日 午後4時9分 非検査例外が悪いわけじゃなくて、非検査例外と検査例外を同じ仕組みでハンドリングさせたことと、 Exception を RuntimeException のスーパークラスにしてしまったこと( Logic Failure を Recoverabble Error の下位においてしまったこと)、構文がイケてなかったことあたりが相互に影響して使い勝手が悪くなってしまったと思ってます。 Java であっても Exception, Error, RuntimeException がそれぞれ Recoverable Error, Universal Error, Logic Failure の意味合いで適切に使い分けられてたら問題がないはず。(編集済)
7:13 AM
Go言語の (err, ret) タプルと panic/rescueが近いのかな
Avatar
Java の標準ライブラリの切り分けも、 NumbberFormatException を Logic Failure にしてしまったこと以外はそんなにまずくないと思う。
7:16 AM
ただ、 RuntimeExceptionException みたいに try / catch 書かなくてもコンパイラに怒られないやつという、使い分けではない挙動ベースでの理解の方が広まってしまって、サードパーティのライブラリでは混乱が大きい気がする。そして、その原因を作ったのは NumberFormatException かもしれない。
Avatar
omochimetaru 6/16/2017 7:18 AM
たしかに
Avatar
もう一つは RuntimeException extends Exception なことかな。
Avatar
omochimetaru 6/16/2017 7:20 AM
そこはかなり無茶苦茶ですよねえ
7:20 AM
もしSwiftにfatalErrorのハンドラが入るとしても、既存のtryがそれを捕まえないようにしないと
Avatar
Effective Java ですすめられてる使い分けはほぼ Swift のエラー分類と同じようになってる。
7:21 AM
既存のtryがそれを捕まえないようにしないと
うん、これが大事だと思ってるんだけど
7:21 AM
We do not currently support propagating exceptions through Swift functions, so changing catch to catch them as well would not be a major compatibility break. とか書かれて若干不安。
Avatar
omochimetaru 6/16/2017 7:22 AM
・・・
Avatar
#other-lang より class User { var id: String = "" } let users: [User] = [] let idToUser = [String: User](uniqueKeysWithValues: users.map { ($0.id, $0) }) がエラーになる error: cannot convert value of type '(@lvalue String, (User))' to closure result type '_' let idToUser = [String: User](uniqueKeysWithValues: users.map { ($0.id, $0) }) ^ @lvalue の扱いがおかしいのかな。 let id だと問題なし。
Avatar
なぜー
Avatar
クロージャに返り値型を明記したら?
Avatar
Swift 4 環境作っとかないとこういうときさっと試せなくて不便だ
Avatar
wandboxオススメです
Avatar
お、 wandbox もう 4 になってるんですか?
Avatar
omochimetaru 6/16/2017 9:08 AM
wandboxって最近はSwiftもいけるのか
Avatar
4.0-devですが
9:08 AM
つい2、3ヶ月前かな?
👍 1
Avatar
let idToUser = [String: User]( uniqueKeysWithValues: users.map { u -> (String, User) in (u.id, u) } ) これはいけましたね。
9:09 AM
as (String, User) でもOK
Avatar
謎だー。他に推論しようがない気がするんですが・・・。
Avatar
@lvalue String を RValue である String に変換しなければならないところなのですが、それができて無くてエラーになっちゃってる感じですね。 master で確認してからバグリポート投げておきます。
Avatar
ありがとうございます。
9:20 AM
さっきの書いてて、普通に↓があったら便利な気がしてきた。 extension Array { func dictionarize<Key: Hashable>(by key: (Element) -> Key) -> [Key: Element] { var result: [Key: Element] = [:] for element in self { result[key(element)] = element } return result } } // [User] to [String: User] users.dictionarize { $0.id }
Avatar
omochimetaru 6/16/2017 9:24 AM
たしかに稀にやりますね その変換
9:25 AM
パット見、 {$.id} をキーにした辞書ができるってことがわからんけど、メソッド名はさておき機能としてはあったら便利そうな気も (edited)
Avatar
extension Sequence { func asDict<K, V>() -> Dictionary<K, V> where Element == (K, V) { return Dictionary(uniqueKeysWithValues: self) } } これでいいんでないかと. (edited)
Avatar
omochimetaru 6/16/2017 9:25 AM
でもそういうあったら便利なやつって無限にあるからなあ
9:26 AM
users.map { ($0.id, $0) }.asDictionary()
9:26 AM
これもいいですね
Avatar
問題は uniqueKeysWithValues が長すぎることな気がしてきた。 _ にしてほしい。
9:29 AM
後は、 toFoo じゃなくて Foo.init で変換を行うようになってることで、処理順序と記述順が一致しない( Dictionary( を最初に書かないといけない)辛さが。
Avatar
っていうかそのものがあった。 let dict = Dictionary(grouping: users) { $0.id }
Avatar
omochimetaru 6/16/2017 9:29 AM
そんなのあったのか
Avatar
おお、知らなかった。
Avatar
あ、けど Dict<String, [User]> になっちゃうや。だめだ。
Avatar
ああ、そういうことか。
Avatar
omochimetaru 6/16/2017 9:30 AM
あ、グルーピングってそっちか
9:31 AM
まーそっちのほうが
9:31 AM
キー重複の可能性が明示的で
9:31 AM
そこの [Users] -> User はもっかい mapするほうが
Avatar
やっぱ↓くらいが落とし所な気が。 let idToUser = users.map { ($0.id, $0) } => Dictionary.init
Avatar
omochimetaru 6/16/2017 9:31 AM
クリアなコードかも
Avatar
Dictionary の値の map ってできたっけ?
Avatar
omochimetaru 6/16/2017 9:32 AM
あれ、できないんだっけ
9:32 AM
そろそろ簡単にできるようになったかな、と思ってた
Avatar
Dictionary.mapは[(Key, Value)]になる
Avatar
仮にできたとしても Dictionary(grouping: users) { $0.id }.mapValue { $0.first! } (edited)
9:33 AM
これはさすがに理解するのに数秒いるのでは・・・。
Avatar
.mapValues(transform:) ですね
👏 2
Avatar
お、あるんですね。
9:34 AM
昔からありましたっけ?なんか昔自作したような・・・。
Avatar
omochimetaru 6/16/2017 9:34 AM
Dictoinary(grouping: users) { $0.id } .mapValues { $0.first! }
Avatar
型で表せないだけで id が一意なことがわかってるケースは多いはずで、 (edited)
9:35 AM
やっぱ↓の方が直接的でわかりやすいと思う。 users.map { ($0.id, $0) } => Dictionary.init
Avatar
omochimetaru 6/16/2017 9:35 AM
一意じゃなかったらクラッシュしてくれる仕様が良いかな?
9:35 AM
=> は反則・・・
Avatar
=> 標準ライブラリにほしい。
Avatar
https://developer.apple.com/documentation/swift/dictionary/2894798-init はクラッシュですね。一意じゃ無かったら。 (edited)
Avatar
おお、素晴らしい。
Avatar
omochimetaru 6/16/2017 9:36 AM
おお
Avatar
Swift 5 の議論始まったら => を Swift Evolution に提案したら通らないかなぁ。応用範囲めちゃくちゃ広いと思うけど・・・。
Avatar
functionに対して変換するようなfunctionを書きたいっていうのがある
Avatar
@tarunon どういうことですか?
9:39 AM
func transform<T, U, X, Y>(_ f: (T) -> U, _ t: ((T) -> U) -> ((X) -> Y)) -> (X) -> Y { ... } (edited)
9:39 AM
ってこと??
Avatar
単純に、Functionは函数の名の通り
9:55 AM
mapとかflatMapとか相応の処理をして変換出来るはず
9:55 AM
クロージャーに対してそういう変換ができるなら、=>の役割は満たせるよなという感じです (edited)
Avatar
うーん、いまいちわからないです。具体的に↓のよくありそうな => のユースケースを書き換えたらどうなるイメージですか? foo() => { $0 + 1 / $0 } vector => { ($0.x, $0.z) } users.map { ($0.id, $0) } => Dictionary.init
🤔 1
Avatar
ん?あれ
10:06 AM
とち狂ってる気がしてきた
10:12 AM
foo.map({ $0 + 1 / $0 })() vector => { ($0.x, $0.z) } //関数じゃない users.(map.map(Dictionary.init)) { ($0.id, $0) } こうなる?いやこれわからんなw
Avatar
なんとなく言いたかった事はわかったw
Avatar
関数に map 相当のものが生えてたらってことですね。
Avatar
関数にメソッド生やせないのはいいとして、Callableなタイプインスタンスを作りたくなるときはあります。 (edited)
Avatar
それは、関数型の値をノミナルに名前付けしたいような時ですか?
10:18 AM
匿名タプルをさけて型名Struct使いたくなるのと同様に
Avatar
そういうことなのかな? Python でいう def __call__ を定義したい。
Avatar
クロージャーを避けて型名がついたクロージャーを使いたい時があるのかなと
Avatar
実行可能なオブジェクト
Avatar
def __call__ だとそれ自体プロパティやメソッドの機能も使えるオブジェクトが作りたいパターン ( C++ でいうファンクタ(誤用
10:19 AM
の話しにも見える
Avatar
// Kotlin class Foo { operator fun invoke(): Int { return 42 } } val foo = Foo() println(foo()) // 42
Avatar
KeyPath が callable だったら users.map { $0.id} じゃなくて users.map(\.id) で ID の一覧得られるのにとか。
Avatar
なるほど
10:21 AM
x に対して何らかのよくやる作用Fがあるとき、 g { f($0, x) } って書くパターンを g(x) と一般に短縮できるのか
10:22 AM
言語としてオペレーターオーバーロードがあるんだから
10:22 AM
関数呼び出しオペレータがあってもいいっすねえ
Avatar
うーん、複雑さが増すデメリットに対して得られるメリットが小さいような?
Avatar
protocol Function { associatedtype Arguments, Returns } かな
Avatar
ですねー。 function type に準拠できるオブジェクト。 とはいえ複雑になるのも確かなので、善し悪しですね。
Avatar
TryParsecを少しいじってた時に、 typealias Parser<In, Out> = (In) -> (Out) ってやって、Parserに対するextensionとか作れなくて残念、って思ったことがあります。 https://github.com/tryswift/TryParsec/blob/swift/3.0/Sources/TryParsec/Parser.swift#L7
TryParsec - Monadic Parser Combinator for try! Swift http://www.tryswiftconf.com/
Avatar
protocol Function { associatedtype Arguments, Returns func do(Arguments)->Returns }
10:39 AM
こういうのでお茶を濁すのは良いと思うんですよね
10:39 AM
良いというか、仕方ないというか
Avatar
SE-0110でRxSwiftのテストケースが死体の山になってる
Avatar
omochimetaru 6/19/2017 5:48 AM
www
Avatar
Xcode 9.0のSE-0110に影響あるところの
2:42 PM
コード生成が
2:43 PM
{ (x1, x2) in x1 + x2 } // as is { let (x1, x2) = $0; x1 + x2 } // to be なのは流石に笑う
2:44 PM
Observable.zip(e0, e1).map { (a0: Int, a1: Int) -> Int in a0 + a1 } // ↓ Observable.zip(e0, e1).map { (__val:(Int, Int)) -> Int in let (a0,a1) = __val; a0 + a1 } これどうなんだw
Avatar
[swift-evolution] [Core team] Addressing the SE-0110 usability regression in Swift 4 https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170619/037616.html
11:44 PM
Therefore, we will “back out” the SE-0110 change regarding function arguments from Swift 4. (edited)
Avatar
めでたい
Avatar
1:32 AM
じゃあRxSwiftのテストケース書き換えはちょっと待った方がいいな
Avatar
omochimetaru 6/20/2017 1:46 AM
おー
Avatar
norio_nomura 6/20/2017 3:33 AM
$0.key$0.0 とかに書き換えたのは戻さないといけなくなるのかな
Avatar
それはSwift3でも動いてたので問題ないはず
Avatar
norio_nomura 6/20/2017 3:40 AM
そうか $0, $1 になるわけじゃないから大丈夫か。
Avatar
swift-4.0-DEVELOPMENT-SNAPSHOT-2017-06-19-a
11:31 PM
この修正 https://bugs.swift.org/browse/SR-5031 が入ったスナップショットがようやく出た。
11:33 PM
SwiftPMで既存の Package.swift を残したまま Swift 4 向けのマニフェストを Package@swift-4.swift として使える様になったはず。
Avatar
norio_nomura 6/21/2017 3:56 AM
macOSで swift-4.0-DEVELOPMENT-SNAPSHOT-2017-06-19-a を使うには Xcode 9 が必要ぽい。
Avatar
あー落とさなきゃ
3:57 AM
Xcode9から落とせるようになってないんやろか
Avatar
norio_nomura 6/21/2017 3:58 AM
なってないです。
Avatar
ないですね、いま確認しました
4:03 AM
おうちMacと会社Macに同じ環境構築するの地味に面倒だ
Avatar
omochimetaru 6/21/2017 4:03 AM
わかる
Avatar
特にXcodeのバージョンを
4:04 AM
8.2と8.3とBetaが要るのがだるい
4:08 AM
あーw
4:08 AM
swift-4.0-DEVELOPMENT-SNAPSHOT-2017-06-19-a これ使ったら、RxSwiftのswift4.0リポジトリが開くとクラッシュするようになった
4:08 AM
笑う
Avatar
omochimetaru 6/21/2017 4:10 AM
ww
Avatar
なんで死んでるのかもわかんねぇな、後で調べよう
Avatar
Playground execution failed: error: Couldn't lookup symbols: __T0s18_HeapBufferStorageCMa
5:20 AM
なんか素のプレイグラウンドも動かない、何もかも間違ってる気がしてきた
Avatar
お。いけたいけた
5:29 AM
プロジェクトからPlaygroundファイルを除去してうまくいきました。
5:29 AM
Playground周りが死んでるみたいですね。
Avatar
norio_nomura 6/21/2017 9:18 AM
swift-3.1-branch が地味に進んでるんだけど、Swift 3.1.xのオフィシャルリリースはまだ出るのかな。
Avatar
class A { static func sharedInstance<X: B>(for type: X.Type) -> A { fatalError() } } protocol B { static var a: A { get } } class C: B { static var a: A { return A.sharedInstance(for: C.self) } } -Osでコンパイラが死
12:07 PM
実行時にCが評価されるからいけると思ったけどダメだった
Avatar
再現しない
Avatar
ありゃ
11:57 PM
本当だ、再現しない
12:00 AM
うーん、またあとで探してみます
🙂 1
Avatar
Xcode 9 beta 2は swift-4.0-DEVELOPMENT-SNAPSHOT-2017-06-19-a 相当という認識で良いのかな
Avatar
swift-4.0-DEVELOPMENT-SNAPSHOT-2017-06-19-aならSE-0110のロールバックはまだですよね
Avatar
だと思います。
12:10 AM
Avatar
次かな
Avatar
Chris Lattner 退職済みなのか。
Work History Tesla VP Autopilot Software January 30 - June 20, 2017
http://www.nondot.org/sabre/Resume.html#Tesla
Avatar
11:25 PM
Avatar
やば
Avatar
norio_nomura 6/23/2017 1:00 AM
"Roll back a portion of SE-0110" を含む swift-4.0-DEVELOPMENT-SNAPSHOT-2017-06-22-a が出てる
Avatar
おっ
1:01 AM
あざす
Avatar
おっ、swiftenv-apiも更新しよ
Avatar
let a1 = Variable<(Int, Int)>((0, 0)) // Expression type 'Variable<(Int, Int)>' is ambiguous without more context let a2 = Variable<(Int, Int)>.init((0, 0)) // 可
1:16 AM
前からこんなんでしたっけ?
Avatar
norio_nomura 6/23/2017 1:19 AM
Variable の定義によるのでは
Avatar
RxSwiftです
Avatar
いや、init省略出来てたはず
1:22 AM
普通に、Variable((0,1))でも動いてたと思うけど
Avatar
そもそも何がambiguousなんだって感じなんですが
Avatar
Playgroundでクラッシュする原因やっとわかった
3:30 AM
Debugging symbolの方落としてたからだw
3:31 AM
でもDebugging symbolじゃないとそもそも、 <unknown>:0: error: unknown argument: '-index-store-path' Command /Library/Developer/Toolchains/swift-4.0-DEVELOPMENT-SNAPSHOT-2017-06-22-a.xctoolchain/usr/bin/swiftc failed with exit code 1 こんな感じでビルドできない、かなしいなぁ
Avatar
To use a https://t.co/LG45yvGKiw toolchain with Xcode 9 in the next few days, run Xcode with “-IDEIndexEnableBoltIndex NO
Avatar
それっぽそう
3:37 AM
見てみます、ありがとうございます
Avatar
いけたっぽい、iOS関連はビルドできないですがMac用ならいけました
3:45 AM
ありがとうございます~
Avatar
うーん
3:53 AM
Tuple→複数引数への展開は許可されたけど
3:53 AM
複数引数(無引数)→Tupleへの変換は消えたままなので
3:53 AM
例えば複数引数のクロージャを{ _ in で引数を無視しようとすると怒られる
3:54 AM
{ (_, _) in ←こうしろ、と
Avatar
{ _, _ in もダメですか?
Avatar
そっちはOKです
👍 1
Avatar
複数引数→タプルはなくてもしかたない気も・・・
Avatar
無くなって初めて、ここが双方向に変換されていたというのを知ったという
Avatar
ですね。意識的に「複数引数→タプル」で変換したことない気がします。
Avatar
うーんよくわからん
4:41 AM
タプルの展開周りまだバグってる気がします
Avatar
norio_nomura 6/23/2017 7:36 AM
Debugging symbolの方落としてたからだw
Debugging symbolのpkgだけでは足りないものがあるので、普通のpkgインストールしてからDebugging symbolのpkgを入れてる。
7:41 AM
Debugging symbolのpkgにはswiftc(swiftへのシンボリックリンク)が無いので、Xcode添付のswiftc(swift)が使われていたのだと思う。
Avatar
なるほど
Avatar
norio_nomura 6/23/2017 7:46 AM
あと、Playgroundだと暗黙で-swift-version 4になるけど、Xcodeプロジェクトだと設定でSWIFT_VERSION4.0にしないとSwift 3.1と同じ挙動になるので「あれ?」ってなったりする。
Avatar
SwiftVersion、Xcode9で開いた場合は4、Xcode8で開いた場合は3みたいにしたいけど
7:46 AM
これ出来ないですよね
7:47 AM
地味にAppKitとかUIKitの変更がしんどくて、#ifで切り替えたいけど無理そう
Avatar
norio_nomura 6/23/2017 7:58 AM
SWIFT_VERSION =3.0でXcode 8と9をコード内で区別するには #if swift(>=3.2) を。
Avatar
おお
7:59 AM
ありがとうございます、助かります
Avatar
norio_nomura 6/23/2017 8:00 AM
Linux版も-swift-version 3はSwift 3.2 (edited)
Avatar
あれ、前は困ったなと思ってたんですが、Xcode9beta2からは
2:15 PM
Swift3.2だと古いAppKit参照してるのかな?
Avatar
なんか一部だけ新しくて一部だけ古いみたいな妙な感じがする、どこか壊れてるかな
Avatar
norio_nomura 6/24/2017 4:50 AM
なかなか大変そう。 [swift-evolution] [Update] Updates to SE-0166 and SE-0167 https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170619/037672.html
Avatar
norio_nomura 6/24/2017 5:01 AM
「デーコード対象がオブジェクトグラフ内で既にデコード済みの場合は、コピーではなくその参照を返す」とか、明文化するらしい。 protocol KeyedDecodingContainerProtocol { /// Decodes a value of the given type for the given key. /// /// If the encountered value is a reference to an existing object previously decoded as part of this object graph, this will return the existing object instead of a new copy of it. func decode<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T } YAMLには別オブジェクトの参照を表す方法があるけど、他にもあるのかな。
5:03 AM
Swiftでの型とシリアライズ先の両方が参照型に対応してないと実現できない。
Avatar
omochimetaru 6/26/2017 4:11 AM
JSONには参照機構は無いですねえ
4:12 AM
シリアライズモデルに参照機構がある場合、(ID, Object)のペアのデコードと、 Idを示すポインタとかハンドルをデコード先言語の参照に差し替える処理を、2パスにわけないと
4:12 AM
参照先がシリアライズ上、参照箇所より後ろに出てくる場合に対応できないので
4:13 AM
この手のデコーダでは参照は取り扱わないほうが無難だと思うけど・・・
Avatar
ちなみにYAMLはこんな感じ https://gist.github.com/bowsersenior/979804
A demo of YAML anchors, references and nested values
Avatar
参照を渡す場合、structだと同一ポインタを指すことになるのかな
Avatar
norio_nomura 6/26/2017 2:09 PM
Codableな型がclassでなければコピーするしかないですよね。
Avatar
うーん、コピーするくらいなら、classじゃなければコンパイルエラーにした方が良いのでは?と言う気がする
Avatar
omochimetaru 6/26/2017 2:13 PM
取り出した値ツリーとしては正しいけど・・・
2:14 PM
変更しなければ等価。
2:14 PM
でも、循環がある場合は無限再帰するね
Avatar
norio_nomura 6/26/2017 2:15 PM
先のYAMLの例だと、デフォルト値を参照して使いまわしています。その場合、デフォルト値がSwift側でも参照として復元されなければいけないかどうか、というのは疑問があります。
Avatar
yamlは参照として復元されることを保障してるわけではない、ならコピーで良さそう
2:19 PM
それならclassもコピーで良いのでは…循環か…
Avatar
norio_nomura 6/26/2017 2:19 PM
JSONSeiralizationNSArray,NSDictionary,NSNumber,NSStringを中間形式として使う様に、たいていのシリアライザは一旦中間形式にしてそう。
2:20 PM
中間形式をValueTypeにしてしまってると、参照型のEncode/Decodeで参照関係も復元するとか、全く無理になってしまう。 (edited)
2:23 PM
僕が書いたlibYAMLのラッパーでも中間形式をenumにしてるので、かなり変更しないと無理だ。
Avatar
あー、中間形式がclassでさえあれば参照関係は十分復元でき…でき…
2:23 PM
出来ないですよね、モデル側もclassじゃないと
Avatar
omochimetaru 6/26/2017 2:23 PM
できないできない
2:23 PM
うん。
2:24 PM
値型に焼き込むところで再帰する
Avatar
ポインタぶち込むとかそういうマッドな事はやりたくないしなぁ
Avatar
norio_nomura 6/26/2017 2:24 PM
モデル、中間形式、シリアライズ形式の全てが参照型をサポートしないといけない。
Avatar
indirectは型の再起についてだけだから、値型に再起構造を盛り込むものではないし
2:26 PM
内部的にはポインタだからゴニョッとやれば出来るかな?
Avatar
omochimetaru 6/26/2017 2:28 PM
それ無理やりやると、
2:28 PM
それを含む値をコピーしようとしたときに
2:28 PM
コピー処理が内部で再帰ループしそう
Avatar
ひぁ
2:29 PM
無限に借金タワーが積み上がるやつだ
Avatar
norio_nomura 6/26/2017 2:29 PM
Realmのオブジェクトをシリアライズしたいとか、そんな要望があったのかなあ。
Avatar
それは間違いなくありそう
Avatar
extension Equatable { /// 一つ以上の同型の値を受け、そのいずれかが self と一致するか否かを返す func isAny(_ arg1: Self, _ args: Self...) -> Bool { return arg1 == self || args.contains(self) } } if intVal.isAny(53, 13, 34, 42, 12) { // something } これを、 switch intVal { case 53, 13, 34, 42, 12: // something default: break } これと同等になるまでインライン最適化して欲しいんだけど、無理そうなので可変長引数に絶望しています。
Avatar
omochimetaru 6/27/2017 6:33 AM
なるほど
6:33 AM
可変長ジェネリックパラメータが入ればいけそうですね (edited)
6:34 AM
そっちなら引数の個数とそれぞれの型に応じて特殊化されるはず。
Avatar
そうなんですよねー。
Avatar
omochimetaru 6/27/2017 6:35 AM
現状だと
6:35 AM
1引数版から5引数版ぐらいまで
6:35 AM
ジェネリックメソッドをオーバーロードしておくのが良さそう
Avatar
extension Equatable { func isAny(_ a1: Self) -> Bool { return a1 == self } func isAny(_ a1: Self, _ a2: Self) -> Bool { return a1 == self || a2 == self } func isAny(_ a1: Self, _ a2: Self, _ a3: Self) -> Bool { return a1 == self || a2 == self || a3 == self } // ... 続く } 😢
Avatar
omochimetaru 6/27/2017 6:37 AM
gybつかってできないですかねw
6:37 AM
自動展開
6:37 AM
Swiftソースのメタ生成ならgyb使うのが一番良さそう
Avatar
SwiftPM がコードジェネレーション的なフェーズをサポートしてくれればいいんですけどね。
Avatar
omochimetaru 6/27/2017 6:38 AM
あ〜
6:38 AM
今ってユーザーシェルスクリプトを挟む余地とかもなかったですよね確か
Avatar
ないですね。 swift build をラップするスクリプトを組まなきゃいけないと思います。それにしても、生成されたソースを Sources に置くとすると、 .gitignore がめんどくさいとかいろいろ問題あって、なかなか痺れます。
Avatar
omochimetaru 6/27/2017 6:41 AM
ウーム 早く入って欲しい。
6:41 AM
生成されたソースもコミットしちゃっても良い気はしますよ
6:42 AM
ライブラリユーザーにとってはgybいらなくて済むし
Avatar
それもアリですね。
Avatar
生成されたソースもコミットしちゃっても良い気はしますよ
むしろこれやらないと SwiftPM で間接的に依存性解決されるときにうまく動かなさそう。
Avatar
ですね。ライブラリとして配布出来ないですね。
Avatar
omochimetaru 6/27/2017 7:24 AM
@koher
むしろこれやらないと SwiftPM で間接的に依存性解決されるときにうまく動かなさそう。
なのでrintaroさんが
SwiftPM がコードジェネレーション的なフェーズをサポートしてくれればいいんですけどね。
と言っているのだとおもいあmす
Avatar
ああ、もしかして現状の話じゃなくて、 gyb が使えるようになった前提でも ignore しなくていいっていう意図だったのかな?
7:26 AM
swift build をラップするスクリプトを組まなきゃいけないと思います。」なので現状の話かと思った。
Avatar
現状は swift build ラッパー書いて前段でジェネレートするにしても、生成後コードをSourcesに入れてコミットしなければライブラリとして公開できない。 swift build がネイティブで プリビルドスクリプトをサポートしてくれれば、その苦労が要らない。
Avatar
omochimetaru 6/27/2017 7:31 AM
もう一つ、その同じラッパー + gyb をインストールした人にしか使えないライブラリにするという条件付きにして、生成物である.swiftはコミットせず.gybだけコミットするパターンがありえるがその場合の.gitignoreはだるい ってパターンも考慮してるかなと思った
Avatar
現状での話で言えばソースもコミットしないと SwiftPM 対応してると言えないし、将来的に gyb が組み込まれた前提だとインストールしなくても SwiftPM 自体に付属してるだろうから追加インストールは不要そう。 .gitignore もそれに合わせて生成。 (edited)
7:32 AM
最初のコメントは、現状でソースコミットしないという選択肢はないんじゃないかという意図です。
Avatar
現状でソースコミットしないという選択肢はない
同意しました。
🙂 1
Avatar
swift-evolution に投稿されてる↓おもしろい。 Never が bottom type になれば ! の代わりに↓ができる。 let last = array.last ?? fatalError(“array must not be empty”)
Avatar
omochimetaru 6/28/2017 2:41 AM
お、なるほど
Avatar
で、今これをやりたきゃジェネリックな fatalError をオーバーロードすればいいよ、と。
Avatar
omochimetaru 6/28/2017 2:41 AM
あれ?ってことは
2:41 AM
return 文 って Never 型の式なのか。 (edited)
Avatar
returnVoid では?
Avatar
omochimetaru 6/28/2017 2:42 AM
kotlinだと
2:42 AM
val last = array.lastOrNull() ?: return 3
2:42 AM
とかできるんですが
2:42 AM
return 文はその実行以降に制御を返さないので
2:42 AM
Never 型の値として型評価できるはず
2:42 AM
fatalError と同じ理屈です
Avatar
ああ、そういう意味か。
Avatar
omochimetaru 6/28/2017 2:43 AM
式の評価が実行の中断を意味する = 値が無い = Never
Avatar
returnなるほど
Avatar
Kotlin の ?: return は特別扱いじゃなくて returnNothing 型の式になってる? (edited)
Avatar
omochimetaru 6/28/2017 2:44 AM
そこまではわからないです フロー解析と型チェックが合体してるイメージだったので
Avatar
Kotlin は制御構文が式だから returnNothing 型の式の可能性も十分にありそう。
Avatar
omochimetaru 6/28/2017 2:45 AM
なるほど。
Avatar
let last = array.last ?? fatalError(“array must not be empty”) に関しては、 ! だと Ligic failure で -Ounchecked で消せるけど↑は消せなくなっちゃうから
2:46 AM
やっぱり ?? fatalError よりも専用の演算子があった方がいいと思う。
2:46 AM
コメント渡せるやつ。
Avatar
guard let v=ov else { return } let v=ov ?? return Neverがbottomかつreturnの左側がNeverならguard使う頻度減る
Avatar
はい。まさにそれが Kotlin でよくやるやつです。
2:51 AM
throw とかも書けます。
Avatar
omochimetaru 6/28/2017 2:51 AM
むしろ if文で returnしてるとIntelliJが ?: に書き換えようぜ〜〜〜って騒ぎ出す
Avatar
?? って T? ?? T ですよね 右辺Neverができる場合どうなるのかよく分からない
Avatar
throwも左側Neverだ、たしかに
Avatar
omochimetaru 6/28/2017 2:52 AM
@t.ae NeverはbottomTypeだから Never is T でなんも問題ない
2:52 AM
Neverはあらゆる型であるわけ
Avatar
ああ、それで評価値としてはTがとれそうだけどNeverで中断されてるから〜ってかんじですか。
Avatar
omochimetaru 6/28/2017 2:53 AM
そうそう。
2:53 AM
取れると思ってその先をコンパイルしても破綻しないので逆説的にいかなる型でもあると言えるって感じ
Avatar
なるほど。
Avatar
↓できた。 // Kotlin fun main(args: Array<String>) { val foo: Nothing = return }
Avatar
omochimetaru 6/28/2017 2:53 AM
何者でもありそうなAny型こそが何者でも無いので面白い
Avatar
やっぱ return 式の型が Nothing なんだ。
Avatar
omochimetaru 6/28/2017 2:54 AM
なるほど
Avatar
swiftの ?? って右辺の評価は左辺がnilであったとき初めてなんですかね
Avatar
@autoclosure だからそのはず
Avatar
omochimetaru 6/28/2017 2:56 AM
うん だから auto closure になってるんじゃなかったかな
Avatar
そうか。auto closureだから遅延するのか
Avatar
omochimetaru 6/28/2017 2:56 AM
auto closure が遅延評価 を意味して 短絡評価と対応するの面白い
Avatar
&& とかも右辺値が @autoclosure で短絡評価を実現してる。
2:57 AM
実際にはクロージャ介さずに効率的に実行してるだろうけど、昔ながらの && の短絡評価を型システム的に @autoclosure で表現できてるのがおもしろい。
Avatar
自前で実装する二項演算子も右辺を遅延させられるのは良いですね
2:59 AM
(この先使うかは知らない)
Avatar
&&?? の associativity は違うっていう豆知識。 && は left、 ?? は right。
Avatar
((a ?? b) ?? c) だと評価が増えるからですかね?
Avatar
omochimetaru 6/28/2017 4:04 AM
おお
Avatar
ですね。 && が left なのは C 合わせだと思います。
Avatar
omochimetaru 6/28/2017 4:04 AM
考え中だけど && も短絡の最適化では?
4:05 AM
left: (a && b) && c right a && (b && c) あれ、ちがうか
4:05 AM
!a で b && c を捨てたいんだから・・・
Avatar
func || (condition: Condition, val: String) -> Condition { return condition.addingOr(string: val) } condition = condition || ">= 42" || "< 12" こういうことをしたい時に right だと出来ない。
Avatar
omochimetaru 6/28/2017 4:07 AM
あーなるほど
4:08 AM
そうか オペレータの結合順はオーバーロードの探索よりも先なのか
Avatar
(a && b) && c で a が 偽の場合、二つ目の && は実際には評価されないのだけど、それは最適化の範囲でやってるみたいです。(&& に副作用があるときは最適化されないです) (edited)
Avatar
omochimetaru 6/28/2017 4:10 AM
なるほどなるほど。
Avatar
&& が left なのは C 合わせだと思います。
なんで C は left なんだろう?
Avatar
考えたけど分からなかった。Cは演算子オーバーロードなくて、&&|| は同じ precedence の演算子は無いので、本当にどっちでもいいと思うのですが。なぜ left に決めたのか。。
Avatar
right の方が自然ですよねぇ・・・。
Avatar
三値論理の可能性を考慮したとか?(左結語じゃないと問題が起こるかは知らない)
Avatar
omochimetaru 6/28/2017 4:22 AM
LL(1) 再帰降下パースでシンプルに実装できるとかそういうのあるかしら
4:24 AM
Cとかだと素朴な実装上の都合だったりするのかなあと思って。
Avatar
どうだろう、 right なら 疑似コードで func parseExprAnd() -> Expr { let lhs = parseExprAtom() if !consume("&&") { return lhs } let rhs = parseExprAnd() return ExprAnd(lhs, rhs) } これで済むけど、 (edited)
4:30 AM
left だとここで畳み込みする必要があって実装的には複雑になりそうな。
Avatar
omochimetaru 6/28/2017 4:32 AM
たしかに。そのシンプルなパターンだとrightになるんですね。
Avatar
func parseExprAnd() -> Expr { var result = parseExprAtom() while consume("&&") { result = ExprAnd(result, parseExprAtom()) } return result } そうでもなかったw
Avatar
あー、 bool がないのは関係あるかも?
Avatar
omochimetaru 6/28/2017 4:35 AM
あたまぐるぐるしてきた
Avatar
Foo *foo1 = ...; Foo *foo2 = ...; Foo *foo3 = ...; Foo *foo = foo1 || foo2 || foo3; (edited)
4:37 AM
のときに foo がどうなってほしいかとか関係ある?
4:37 AM
NULL である可能性を考慮して。
4:38 AM
あれ?結合順は関係ないか? (edited)
4:38 AM
ってか元の omochimetaru の bool 発言消されてるw
Avatar
(foo1 || foo2) || foo3 でも foo1 || (foo2 || foo3) でも 左辺優先は変わりないような。
Avatar
ですね。
4:40 AM
となるとパフォーマンスを除けば副作用がある場合しか関係ないかぁ。
Avatar
副作用も結合順は関係なくないですか?
Avatar
短絡だからそうか
4:42 AM
単に (a || b) || c だと atrue のときに 2 回評価されるけど、 a || (b || c) だと 1 回という違いしかないのか。
Avatar
let fooDefault = 12 public func foo(x: Int = fooDefault) { // error: let 'fooDefault' is internal and cannot be referenced from a default argument value } Swift4 で public な関数の引数デフォルトに internal 以下の値が使えなくなりました (edited)
Avatar
omochimetaru 6/28/2017 7:46 AM
正しい感じがする
Avatar
影響受けるひとそれなりに居る気がする。
Avatar
逆に今までどうやって動いてたんですかこれ
Avatar
omochimetaru 6/28/2017 7:47 AM
呼び出し側がinternalのシンボルを実は見えていたってことですよねえ
Avatar
感触としては引数なしのオーバーロードが同時に定義されてたように見えてた?
Avatar
omochimetaru 6/28/2017 7:49 AM
かき心地としてはそうだね
7:49 AM
でも実際にエントリポイントが作られてるわけじゃないからバイナリとしてはそうじゃないはず
Avatar
ふむ。
7:52 AM
実際のところデフォルト引数が呼び出し側からアクセスできなかったとしてあんま問題ない気もするんですよね。 呼び出し側の影響を受けるのは #line とかくらい?
Avatar
これが導入されたコミットのコメント見ると、Swift4ではデフォルト値の扱いが変わったみたいですね。 https://github.com/apple/swift/commit/d65d1d25f9a9248ac28494070e7246e603f60c43#diff-efafad982d57180bb1e93bfb6d2cdc0dR1213
…rguments model Piggybacks some resilience diagnostics onto the availability checking code. Public and versioned functions with inlineable bodies can only reference other public and internal enti...
Avatar
うーん、イミュータブルな値だったら別に使えてもいい気もするけどなぁ。 private let maxN = 42 func foo(_ x: Int, max: Int = maxN) -> Foo { ... } func bar(_ x: Double, max: Int = maxN) -> Bar { ... }
Avatar
そもそもデフォルト値の評価タイミングは
Avatar
複数箇所で使うから 42 とハードコードしたくない場合とか。
Avatar
関数実行時のタイミングだが、宣言側の文脈で解釈可能な値が出てくるみたいな
7:58 AM
そんな感じの動きだった気がする
7:58 AM
関数実行側の文脈で解釈可能な値に変わるのかな
Avatar
むしろ以前はデフォルト引数は呼び出され側で評価されてた?
Avatar
@DevAndArtist @slava_pestov @SmileyKeith @jckarter This restriction
  • allows default arguments to be inlined (eventually)
  • allows showing the default in the module interface (eventually)
Avatar
In Swift 4 mode, default argument bodies are inlined into the caller.
Avatar
そのはず
Avatar
その場合 #line はどうだったんだろうってなる
Avatar
そうそう、#lineと#fileとか、こいつらの挙動からCaller側判定だろって思い込んでいて、
8:02 AM
ひどいめにあった
Avatar
その辺は特別扱いされていたのは確かで、
Avatar
protocol Foo { static var value: String { get } } extension Foo { static var value: String { return "real" } } extension Foo { static func printValue(_ value: String = Self.value) { print(value) } } struct FooImpl: Foo { } FooImpl.printValue() // "real" protocol Test { } extension Foo where Self: Test { static var value: String { return "test" } } struct FooTest: Foo, Test { } FooTest.printValue() // "test"
8:03 AM
↑実験用コード
Avatar
これをTestを別frameworkに分離させると
Avatar
omochimetaru 6/28/2017 8:04 AM
え、#line って呼び出し側の行数が出るんじゃないの?
Avatar
挙動が変わる
8:06 AM
これ以外は callee 側で初期化するっていう形だったと思います。(嘘でした) (edited)
8:07 AM
それを caller 側に統一した(したい)って事なのかな? (edited)
Avatar
omochimetaru 6/28/2017 8:07 AM
ええっ、そうだったのか・・・
8:07 AM
呼び出し側では何を渡してたんだ・・・?
Avatar
8:08 AM
これ実際の動きと直感的なイメージが乖離していて辛いことの1つだったんで、caller側に統一してくれるのは嬉しい
😄 1
Avatar
omochimetaru 6/28/2017 8:08 AM
@tarunon の書いてるのは printValueの Self.value の評価値が変わるってことかね
8:09 AM
Swift3ではTestのほうのファイルがわかれていると、callee側で評価されているから
8:09 AM
realが出ちゃったと
8:09 AM
ああ、呼び出され側で評価ってそういうことか 実行時の評価のことじゃなくて (edited)
Avatar
ああ、 デフォルト値を取得する関数が別で定義されていたのでした。
Avatar
omochimetaru 6/28/2017 8:10 AM
マジ
8:10 AM
あーまあーなるほど
8:11 AM
それならこのようなことは起こってはいなかったのか > 呼び出し側がinternalのシンボルを実は見えていたってことですよねえ
8:11 AM
デフォルト引数を埋めるためのだけのAPIが別途空いていたならおかしくはない
Avatar
%operand = ... %func_print = function_ref Swift.print %func_separator = function_ref Swift.print.default.separator %func_terminator = function_ref Swift.print.default.terminator %separator = apply %func_separator() %terminator = apply %func_terminator() %result = apply %func_print(%operand, %separator, %terminator) こんな感じか。 (edited)
Avatar
omochimetaru 6/28/2017 8:13 AM
おお。
Avatar
やばいコード思いついた。 let a: Never = preconditionFailure() print("Hello") print(a) これ、 -Ounchecked でコンパイルしたら preconditionFailure() をすり抜けるから Never を返す関数の戻り値を使うコードが実行されてしまう。
Avatar
これって preconditionFailure 自体が消えるはずですけどaはどうなるんだろう? (edited)
Avatar
ちなみに実行結果は Segmentation fault: 11
Avatar
omochimetaru 6/28/2017 8:33 AM
ていうか Ouncheckedのアンチェックドは
8:33 AM
そういう意味なのでは?
Avatar
assert でリリースビルドだったら?
Avatar
omochimetaru 6/28/2017 8:34 AM
そもそも
8:35 AM
クラッシュするかもしれないし
8:35 AM
aが空ストレージになるかもしれないし
8:35 AM
aのストレージすら消えて一個下のスタックフレームの上部を見るかもしれないし
8:35 AM
もっとアグレッシブに、その先のprint自体削除するかもしれないし
8:35 AM
未定義動作っていうのは何をやってもいいって意味でもあるから。
8:36 AM
その仮定をおけるからこそ、前提条件が常に正しいことを前提に最適化がいろいろ工夫できるのだし。
Avatar
assertionFailureVoidだった
Avatar
omochimetaru 6/28/2017 8:36 AM
assert系のファミリーはuncheckedでも削除されないんだっけ
Avatar
いや
8:36 AM
assert は -O でも削除される
8:37 AM
fatalError は削除されない
Avatar
omochimetaru 6/28/2017 8:37 AM
逆か
8:37 AM
削除されるからこそ
8:37 AM
脱出を前提に置けないのか
Avatar
preconditionFailure っていつ使うの?よく意味わかんなくない?
8:37 AM
precondition はわかるけど
Avatar
ですね。 uncheckedでしか消えないpreconditionFailureNeverなのはうなずける
8:37 AM
@koher switch
Avatar
omochimetaru 6/28/2017 8:37 AM
logic failureでバグってるときじゃないスカ
Avatar
@t.ae if の条件で書けないときってこと?
Avatar
switchでdefault: preconditionFailure()とかやります
Avatar
precondition を使わずに preconditionFailure を使うとき。確かに switch はあり得るかも。
8:39 AM
default: fatalError() より default: preconditionFailure() の方が筋が通ってるね。
8:39 AM
なるほど。
Avatar
omochimetaru 6/28/2017 8:39 AM
if <condition> { preconditionFailure() } の形でかけないケースですよね switchはたしかにそう
8:39 AM
↑の形になるときは precondition を普通に使えばよいから。
Avatar
うん。
Avatar
omochimetaru 6/28/2017 8:40 AM
お、わかった
8:40 AM
Result.flatMapError { preconditionFailure() } とか。
Avatar
なんで flat
Avatar
omochimetaru 6/28/2017 8:41 AM
mapErrorか
8:41 AM
Either<T, HogeError> . mapError < T -> Never > の式は Either<T, Never> になるし
8:41 AM
型的にも意味のあるロジックになる
8:42 AM
なんらかの前提条件でHogeErrorrが絶対に入ってないことがわかってるときのキャスト。
Avatar
それは Either<T, Never> じゃなくて T にしてほしいねw
Avatar
omochimetaru 6/28/2017 8:42 AM
たしかにw
Avatar
そこらへんが Union だとキレイだよなぁ
8:42 AM
T|NothingT になるから。
Avatar
omochimetaru 6/28/2017 8:43 AM
でもさっきのなら fatalError でいいのか?
Avatar
絶対に実行されない文で preconditionFailure()使うメリットがあるんです?
8:43 AM
突入しないならfatalErrorでもなんでも良いのでは
Avatar
omochimetaru 6/28/2017 8:43 AM
fatalErrorは -Ouncheckedでも消えない?
Avatar
絶対に実行されないことを明示するために preconditionFailure を書くんじゃないでしょうか。
8:43 AM
fatalError は消えない。
Avatar
omochimetaru 6/28/2017 8:43 AM
なるほど
Avatar
ライブラリでユーザー入力の値を確認したいときとか
Avatar
現実的には、消えてしまうメリットはないし
Avatar
omochimetaru 6/28/2017 8:43 AM
fatalErrorは、ある意味、ある条件で死ぬっていう明示的なコードなのか。
8:44 AM
preconditionFailureは、その条件は絶対に成立しない
8:44 AM
表明になる
Avatar
preconditionFailure を使うべきケースではすでに条件分岐は終わってるから
Avatar
万人に理解できるものではなさそうだ
Avatar
削減できてうれしい理由はないし
8:45 AM
コード上、ここには絶対に到達しないということを明示するということを除けば
8:45 AM
メリットはなさそうに見える(むしろ、バグで万が一突入したときに、 -Ouncheckec で消えてしまうデメリットがある)。
Avatar
omochimetaru 6/28/2017 8:46 AM
@koher いや
8:46 AM
preconditionfailureは -Ouncheckedで削除されるってことは
Avatar
消えてしまうために
Avatar
omochimetaru 6/28/2017 8:46 AM
分岐の中身が消えるから
8:46 AM
分岐自体が消えるチャンスが有る
8:46 AM
最適化で
Avatar
うーん
Avatar
omochimetaru 6/28/2017 8:47 AM
fatalErrorは絶対に消えないってことは、fatalErrorでクラッシュする可能性を残さないといけないから分岐が削除できない
Avatar
switchdefault だと意味がなさそうだけど、何らかの最適化ができるケースはあり得るか。
Avatar
omochimetaru 6/28/2017 8:47 AM
まあでも 解析できそうなif文のケースでは precondition を使えってなりそうだけど。
Avatar
switchの最後に使うのか
Avatar
fatalErrorに条件付きのがないのもそのせいっぽいですよね
Avatar
val nonnull = nullable ?: preconditionFailure()
8:49 AM
みたいなコード( Kotlin なのか Swift なのか)で最適化上の意味があるのか。
Avatar
omochimetaru 6/28/2017 8:49 AM
Avatar
あー
Avatar
implicitly系が最適化オプションで消滅したほうが良いのではという気がしないでもない
Avatar
じゃあ、 Never as a bottom type
8:50 AM
ができれば
8:50 AM
let foo = fooOrNil ?? preconditionFailure() (edited)
8:50 AM
Avatar
omochimetaru 6/28/2017 8:51 AM
@tarunon !とかは -Ouncheckedできえるらしいよ
Avatar
-Ouncheckedlet foo = fooOrNil! と等価になるのか。
8:52 AM
それは素晴らしい!
Avatar
なるほどー
Avatar
omochimetaru 6/28/2017 8:52 AM
ですね
8:53 AM
お?ってことは
8:53 AM
前話してた ! 使うなら理由をかけ が
8:53 AM
できる?
Avatar
うん
Avatar
omochimetaru 6/28/2017 8:53 AM
preconditionFailure は理由わたすところあるんだっけ
Avatar
ある。
Avatar
omochimetaru 6/28/2017 8:53 AM
! 演算子禁止の機運がwww
Avatar
メッセージ渡せる。素晴らしい。
Avatar
try! に対しては
8:54 AM
try? xxx ?? preconditionFailure(reason)
8:54 AM
これでOKか
Avatar
ですね。
Avatar
omochimetaru 6/28/2017 8:54 AM
それだと例外に入ってる情報が消えない?
Avatar
あー
8:54 AM
確かに。
Avatar
try!なら例外情報出せるんでしたっけ
Avatar
omochimetaru 6/28/2017 8:55 AM
なんかダンプされた気がするようなしないような
Avatar
むー、エラー情報と ! の理由を両立させるの難しそう。。。
Avatar
!禁止、正直あんまり生産性無いなと最近思うようになってきた
8:56 AM
末尾にコメントでも書いときゃ良いんじゃねぐらいの気持ち
Avatar
omochimetaru 6/28/2017 8:56 AM
実際にやってみたってこと?
Avatar
!禁止は前の前のプロジェクトでやってた
8:57 AM
前のプロジェクトは!はゆる~く許可してた。
Avatar
! 禁止は、 forced unwrapping を禁止する意味じゃなくて
8:57 AM
forced unwrapping を使うなら理由を明記することを強制する、の意味ですね。
8:58 AM
let value: Int = Int(textField.value) ?? preconditionFailure("UI の制約で整数しか入力できないので絶対に nil にならない。") (edited)
9:01 AM
let first: Int = array.first ?? preconditionFailure("この array は必ず空でないことが保証されている。")
Avatar
コメントで良いのでは?という気がしている
Avatar
デバッグ実行時にここに到達してしまったときに、メッセージが出たらデバッグしやすくないですか?
Avatar
preconditionfailure + 文言が長くて一行で書ける嬉しさが減ってる感
9:03 AM
guard let ですでに実現できるんですよね
Avatar
デバッガ有りで議論するなら、その行にジャンプするから別にコメントでよくねというのがあって
9:03 AM
preconditionfailureで嬉しいとすると、デバッグビルドでQAやってログに残るとか
Avatar
guard let-Ounckecked で最適化されない問題がある。
Avatar
でも、QAはリリースビルドでやるべきですね
Avatar
ああ、そうだった
Avatar
@tarunon 言語レベルの話と、デバッガを入れたツールレベルでの話は別だと思うので、言語レベルで追跡できるのはより望ましいと思います。
Avatar
!ってスタックトレース出ないんでしたっけ
Avatar
あとは、 ! 禁止のコード規約を採用して ?? precondition を使えば、コメントを強制しやすいとかですかね。
9:07 AM
preconditionFailure にコメント必須じゃないのが微妙ですが。
9:07 AM
func logicFailure(_ message: String) -> Never { preconditionFailure(message) } (edited)
9:08 AM
preconditionFailure も禁止して↑を使わせれば強制できますね。
Avatar
フーム
10:30 AM
private func failure<T>(message: @autoclosure () -> String) -> T { preconditionFailure(message) } infix operator !! func !!<T> (lhs: @autoclosure () throws -> Optional<T>, rhs: @autoclosure () -> String) -> T { do { return try lhs() ?? failure(message: rhs) } catch { print(error) // logging return failure(message: rhs) } } let num = Int("123") !! "絶対に数字" let data = try Data(contentsOf: URL(string: "https://www.google.com") !! "Google") !! "オフラインはあり得ない"
Avatar
おお、 try もカバーですね。例のスレッドに提案してくださいw
Avatar
どのスレですかw
10:35 AM
!をinfix operatorも可にして右に理由を書けるようにすれば良いんじゃないかな~とか思ったんですが
10:35 AM
try!がダメすぎてダメ
Avatar
なるほど
Avatar
これめっちゃいいですね
10:40 AM
おしゃれ
Avatar
throws funcからfunc, Optional<T>からTへの暗黙変換が成り立つので
Avatar
!をinfix operatorも可にして右に理由を書けるようにすれば良いんじゃないかな
これはできるんじゃないですか?カスタムの ! は作れないですが、標準ライブラリに組み込むなら。
Avatar
いや
10:41 AM
tryがですね
10:41 AM
なんでこいつは左にいるんだ
Avatar
try foo() ! "message" ならいいのでは?
Avatar
ウーンそれはそうなんですが
10:41 AM
try!との対称性とか
Avatar
try foo() !! "message" でも同じじゃないですか?
Avatar
それはそう
10:42 AM
いやだから
10:42 AM
文句を言っているのはtryの場所が良くないねという話です
Avatar
try の場所はダメですね。右であるべきだった。
Avatar
人類がもうちょっとたくさん記号が使えれば
Avatar
まあでも ! が統一されていることは重要だから、結局 foo! の形になるんじゃないでしょうか。
Avatar
あとぶっちゃけ、Optionalはネストするけどthrowはネストしないとか
10:44 AM
まあそこまで対称な概念でもないしまあいいかな
Avatar
ネストするんじゃないですか?
10:46 AM
// ネスト do { ... = try foo() do { ... = try bar() } catch _ { ... } } catch _ { ... } (edited)
10:46 AM
// フラット do { ... = try foo() ... = try bar() } catch _ { ... } (edited)
10:47 AM
throws -> FooResult<Foo> と捉えたら、前者がネストした map で後者が flatMap だと思います。
Avatar
型としてネストしてないという意味です
Avatar

デコード先の型を推論させたいという、ヒトなら誰しもが持つ欲望

@inamiy さんのスライド [Swift 4 Codable // Speaker Deck](https://speakerdeck.com/inamiy/sw...
12:24 AM
decoder.decodeの引数にデフォルト値を入れた方が良いという話
12:24 AM
これSwift evolutionに投げれば議論できるんですかね?
Avatar
できるんじゃないでしょうか。SE-0110もswift-evolutionへの投稿をきっかけに見直されましたし。
Avatar
func decode<T>(_ type: T.Type=T.self, from...
12:26 AM
こうすると皆が幸せな世界になる
12:26 AM
投げるか
Avatar
先日のswift-evolutionに上がってたCodableのUpdate、PRが出てる。 https://github.com/apple/swift/pull/10667
What's in this pull request? As laid out in a proposed update to SE-0166 and SE-0167, there are optionality updates that we wanted to introduce to the Codable API. This implements the remainder of ...
Avatar
SE-0110見直しのきっかけになったのは↓ですね。 https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170522/036773.html
Avatar
decodeの引数にInt.Typeとかあるのちょっと
12:29 AM
冗長すぎでは、返り値オーバーロードしたくないモチベーションなのかなぁ
Avatar
これ、ビルド通らないよ。

デコード先の型を推論させたいという、ヒトなら誰しもが持つ欲望

@inamiy さんのスライド [Swift 4 Codable // Speaker Deck](https://speakerdeck.com/inamiy/sw...
12:34 AM
Playground execution failed: error: PlayNow-20170629.playground:3:41: error: use of unresolved identifier 'data' return try decode(T.self, from: data) ^~~~ error: PlayNow-20170629.playground:8:41: error: use of unresolved identifier 'data' return try decode(T.self, from: data) ^~~~ 多分、プレイグラウンド内でグローバルスコープの data をデコードしてる。
Avatar
メンション飛ばしておこう @takasek
Avatar
ああ、外から見たらIntを明示してるように見えるのか
12:42 AM
okok
Avatar
norio_nomura 6/29/2017 1:21 AM
decoder.decodeの引数にデフォルト値を入れた方が良いという話
Decoderプロトコルにdecode()メソッドは含まれません。PR出すだけで良い気がする。
Avatar
1:21 AM
やってみよう
Avatar
norio_nomura 6/29/2017 1:24 AM
自前のDecoderにさっきのエクステンションを足してみたけど、とりあえず問題なさげ。
1:25 AM
新しくなる実装ではまだ試せてない。 https://github.com/apple/swift/pull/10667
What's in this pull request? As laid out in a proposed update to SE-0166 and SE-0167, there are optionality updates that we wanted to introduce to the Codable API. This implements the remainder of ...
Avatar
これマージされないとPR出せない気がする
Avatar
norio_nomura 6/29/2017 1:30 AM
JSONDecoder.decode()PropertyListDecoder.decode()だけなら問題ない気がする。
Avatar
これEncoderだけなのか
Avatar
norio_nomura 6/29/2017 1:35 AM
Decoderも含んでるけど、変更箇所とは関係ないかなと。
1:37 AM
*ContainerProtocolの方は微妙。
Avatar
KeyedDecodingContainerProtocol、こっちもやらないと多分意味がない上に、protocolだからデフォルト引数とか出来ない気がする
Avatar
かやまま
Avatar
protocolならextensionに引数なしメソッド書くほうが筋が良いな
Avatar
norio_nomura 6/29/2017 2:24 AM
protocolの変更だとswift-evolutionに投げた方が良い気がする。
Avatar
ですね、投げよう
Avatar
norio_nomura 6/29/2017 2:33 AM
個人的には型パラメータ必須が良いと思う。
2:35 AM
プロパティの型が変わったことに、ランタイムエラーでしか気付けなくなりそうだから。 (edited)
2:36 AM
まあ、コンパイラによる自動生成を使っていたら、どちらにしても気付けないけど。
Avatar
うーん、Codableのプロパティの型を書き換えちゃう人、別にdecodeが型必須であってもコンパイルしてエラー出て修正して…ってやっちゃう気がしていて、省略してもほぼ同じなのではという気がする
2:59 AM
あれっ、なんで通らないんだろう
2:59 AM
みてみます
Avatar
norio_nomura 6/29/2017 3:00 AM
func decode<T: Decodable>() throws -> T { switch T.self { case is Bool.Type: return try decode(Bool.self) as! T case is Int.Type: return try decode(Int.self) as! T … このswitch文って、最適化で消えたりするのかな? (edited)
Avatar
これ多分効率よくないんで
Avatar
@norio_nomura let data = """ { "id": 100, "text": "text", "url": "https://www.yahoo.co.jp", "option": null, } """.data(using: .utf8)! これペーストし忘れてたりしませんか?
Avatar
元から型付きであるdecodeは返り値オーバーロードさせたほうが良いと思った
Avatar
たしかに
Avatar
norio_nomura 6/29/2017 3:04 AM
@takasek extension JSONDecoder { func decode<T: Decodable>(from: Data) throws -> T { return try decode(T.self, from: data) } } ここでグローバルスコープのdataをデコードしてますよ。 (edited)
Avatar
あ!本当ですね
3:06 AM
直しておきます
3:06 AM
あとは >元から型付きであるdecodeは返り値オーバーロードさせたほうが良いと思った func decode(forKey key: Self.Key) throws -> Int { return try decode(Int.self, forKey: key) } こんなですね
Avatar
です
Avatar

デコード先の型を推論させたいという、ヒトなら誰しもが持つ欲望

@inamiy さんのスライド [Swift 4 Codable // Speaker Deck](https://speakerdeck.com/inamiy/sw...
👍 5
Avatar
こんなの入ってたんだ https://github.com/apple/swift/pull/7125
Added default implementations for ExpressibleByUnicodeScalarLiteral and ExpressibleByExtendedGraphemeClusterLiteral init(unicodeScalarLiteral value: UnicodeScalar) init(extendedGraphemeClusterLiter...
2:49 AM
自分のC++開発でSwiftのgybを使ってみようかと思っているんですが
2:50 AM
使い方の文書が見つからない
Avatar
utils/gyb --help くらいしか。。
Avatar
omochimetaru 6/30/2017 2:52 AM
なるほどw
2:53 AM
googleのpumpよりgybのほうが行数が多いけど(どっちもワンファイルpython
2:53 AM
後発だから何か進化があると期待している
Avatar
pump.py 使ったことないからドキュメント読んでみましたが、 gyb はもっと単純な感じで、php 的なテンプレートエンジンです。
Avatar
omochimetaru 6/30/2017 3:21 AM
pumpもPHP的なテンプレートエンジンだと思う
3:24 AM
↑前つかってみたときの例
Avatar
Python のすべての文法が使えるっていう意味です。
Avatar
omochimetaru 6/30/2017 3:28 AM
gyb は %{ }% でpythonなんでもかけるのか
3:28 AM
pumpは $(exp)で exp ::= simple_expression_in_Python_syntax だけど
3:29 AM
多分pythonでlambda文とかに与えられる制限つよい1文だけのやつっぽいな
Avatar
import でも def でも 何でも。 ${exp} は式であれば何でも書けますね。
Avatar
omochimetaru 6/30/2017 3:30 AM
なるほど。そこは大きな違いですねえ
3:42 AM
ここ見たらオ〜ってなった
Avatar
omochimetaru 6/30/2017 6:45 AM
gybの % for: による展開だと
6:45 AM
x0 + x1 + x2 とか x0, x1, x2
6:45 AM
みたいな、最後の1個だけは演算子や区切り文字を出さない
6:45 AM
パターンは書けない・・・?
6:46 AM
, のケースは その中で inline で if 書くか・・・
Avatar
${", ".join(array)} とかじゃだめすか?
Avatar
omochimetaru 6/30/2017 6:55 AM
そうなっちゃいますよね うーんむ
6:55 AM
テキストをロジックでjoinするというよりロジックでjoinしてテキストを作る形になっちゃって微妙な気分
Avatar
% for elem in arry[0:-1]: ${elem}, % end ${arry[-1]} (edited)
Avatar
omochimetaru 6/30/2017 7:14 AM
あ〜良さそうです
Avatar
omochimetaru 6/30/2017 9:09 AM
要素数が0の場合に何も出さないようにしたいけどそれだと駄目か。
Avatar
omochimetaru 6/30/2017 9:22 AM
なんでもpython書けるのいいな。よくなってきた
9:22 AM
pumpより良い
9:25 AM
endが無いpythonに % end を足してスコープ挟んでるのも面白い・・・
9:25 AM
なんなんだ・・・
Avatar
% end がアンバランスに存在すると、それ以降何も出力されなくなるのがバグなのか未だに知らず。 % if foo: func foo() {} % end foo() % end ここ出力されない
Avatar
omochimetaru 6/30/2017 9:29 AM
過剰なendならエラーとか出してくれないんですかw
Avatar
バグだったら swift リポジトリに PR のチャンス?w
Avatar
omochimetaru 6/30/2017 9:29 AM
地味にありだな・・・gybこれ単体でいいぞ
9:29 AM
惜しむべくはpythonを書くのがつらいってことだけど・・・
9:33 AM
cpp-rhetoric - small fundamental library for modern C++ programming.
cpp-rhetoric - small fundamental library for modern C++ programming.
Avatar
おお
Avatar
omochimetaru 6/30/2017 9:34 AM
gybの冒頭のここらへんがpythonへの呪詛 def join(xs, j): return j.join(xs) def ifx(c, y, n): if c: return y else: return n
9:35 AM
Swiftのメタ生成にも使いやすそうだ
Avatar
Addresses issue SR-331 by adding warning fix-its for possible Unicode confusions. This check only runs after either the lexer encounters an invalid character or an identifier fails to resolve. (All...
Avatar
omochimetaru 6/30/2017 9:49 AM
ww
Avatar
norio_nomura 7/1/2017 1:06 AM
コード生成は最近Sourceryをよく見る。 https://github.com/krzysztofzablocki/Sourcery
Sourcery - Meta-programming for Swift, stop writing boilerplate code.
👀 1
Avatar
omochimetaru 7/1/2017 8:34 AM
はは~
8:35 AM
こいつは.swiftにコメントで注入するからソースがswiftを保てるんですね
Avatar
gybやってみたけど、SPMのビルドに噛ませるのどうやったらいいんだろ
Avatar
omochimetaru 7/3/2017 4:22 AM
$ swift build にかませる方法が無い・・・
Avatar
オワタ
Avatar
omochimetaru 7/3/2017 4:23 AM
a.swift.gyb と 生成物 a.swift をコミットしておけばライブラリとしては配布できるけど
4:23 AM
他のコントリビュータも a.swift.gyb を編集する必要がある
4:24 AM
その前提でライブラリ作者は自分で叩くのが良い
Avatar
ふーむ
4:24 AM
enum-convertible - Protocols for enum abstraction.
4:24 AM
ここ弄れば任意個のEnum生成できるようにしたけど
4:24 AM
spmはそもそもxcbuildじゃないからここ見てくれない
Avatar
omochimetaru 7/3/2017 4:24 AM
ですね
Avatar
gybの生成物、###sourceLocationのパスが絶対パスなのが非常に辛いんだけど相対パスに変えられないかな
9:18 AM
おもちくんはそもそもこの行消してるのか
Avatar
omochimetaru 7/3/2017 9:19 AM
うん。 --line-directive "" で消してる。
Avatar
お、消えた消えた
Avatar
omochimetaru 7/3/2017 9:19 AM
仕組み的に相対パスでうまく動くのかよくわからんしな
Avatar
thx、これならコミットできるや
9:19 AM
そうなんだよね
Avatar
// ###sourceLocation はコンパイラ自体には影響与えないです。(ただのコメント) なので、エラーなどは生成後のファイル名と行数で出ます。 これを utils/line-directive と合わせて実行すると、 gyb のファイル名、行に直してエラーを表示してくれるようになります (edited)
👀 2
9:30 AM
utils/line-directive は コンパイラからのエラー出力を正規表現で拾ってるだけ。
Avatar
omochimetaru 7/3/2017 9:31 AM
コンパイラ/デバッガの規格の外にある仕様だったんですね。
Avatar
一個だけ、 // ### で始まるコメント行は無視されるっていう挙動があって、何に関係あるかっていうと /// コメント1 // ###sourceLocation(...) /// コメント2 func foo() {} だと、コメント1 と コメント2 が両方とも DocComment として有効になる。 // ### で始まらないコメントだと、そこで切れてしまうので、 コメント2 だけが foo() の DocComment になります。 (edited)
Avatar
omochimetaru 7/3/2017 9:39 AM
あ〜 コメントは生成物で sourceLocationは生成に関する情報だから
9:39 AM
それを退避するルールが無いとコメントの中の構文(doccomment)があるときに困るのか
9:39 AM
コメントが2レイヤーある
Avatar
コード生成のためにGenericsパラメータを改行して列挙するようにしてみたんだけど、俄然こっちのほうが読みやすいな。これコーディング規約に突っ込んでも良さそうだ。
9:40 AM
public func animatedItems<C0, C1, C2, C3, C4, S, O>(for type0: C0.Type, _ type1: C1.Type, _ type2: C2.Type, _ type3: C3.Type, _ type4: C4.Type) -> (O) -> Disposable where S: AnimatableSectionModelType , O: ObservableType , O.E == [S] , S.Item: Enum5Convertible , C0: Reusable , C0: UICollectionViewCell , S.Item.T0 == C0.Dependency , C1: Reusable , C1: UICollectionViewCell , S.Item.T1 == C1.Dependency , C2: Reusable , C2: UICollectionViewCell , S.Item.T2 == C2.Dependency , C3: Reusable , C3: UICollectionViewCell , S.Item.T3 == C3.Dependency , C4: Reusable , C4: UICollectionViewCell , S.Item.T4 == C4.Dependency ここまで行くと改行してないと読めない
Avatar
omochimetaru 7/3/2017 9:40 AM
カンマ右に置こうよ・・・
Avatar
右だと生成めんどくさくなるよ
Avatar
omochimetaru 7/3/2017 9:41 AM
左でも1個めを特別扱いしてるのは同じじゃない?
9:41 AM
1個めの左にはカンマがないっていう制御が必要
Avatar
1個めは繰り返さない型パラの指定にしてる
Avatar
omochimetaru 7/3/2017 9:42 AM
なるほど
Avatar
,が左なのはRx本体側のコードに習ってるよ
Avatar
omochimetaru 7/3/2017 9:42 AM
% for i in range(n): std::is_convertible<U${i}, T${i}>::value${ifx(i < n-1, " &&", "")} % end
9:42 AM
自分はこんなふうにした
9:43 AM
最後の行だけ && が出ない。 (edited)
Avatar
if文イヤイヤ病だった
Avatar
joinでもいけそう?
Avatar
omochimetaru 7/3/2017 9:44 AM
これはif文じゃなくて自作のifx関数だけどねw (pyhtonの3項演算子はキモい
Avatar
,左のRxSwiftのコードはDelegateProxyの実装に頻繁に見られる
Avatar
omochimetaru 7/3/2017 9:44 AM
joinだと行自体をpython側の文字列として構築することになるんで微妙なんですよね
9:44 AM
なるべく多くをテンプレートリテラルとして書きたい
9:45 AM
@tarunon きもちわるい・・
Avatar
なるほど、確かにpython側でロジック入れすぎると旨味薄い感あります
Avatar
MultilineStringLiteralが無かった時
9:45 AM
return "xxx" + "yyy" + "zzz" (edited)
9:46 AM
こんな感じにしてたけどこれと似たようなものだと思う
Avatar
omochimetaru 7/3/2017 9:47 AM
それも嫌や
Avatar
俺は左のほうが好きなんだよね
Avatar
omochimetaru 7/3/2017 9:47 AM
そっか
Avatar
return や where が左に存在していて
9:48 AM
その後改行した時に同じように左側に,+ がある (edited)
Avatar
omochimetaru 7/3/2017 9:48 AM
ArrayやDictoinaryリテラルのときは?
Avatar
そいつらはカンマ右だわ
9:48 AM
やべぇ
Avatar
omochimetaru 7/3/2017 9:48 AM
そこはちがうんかい
Avatar
でも
Avatar
文字列の複数行は確かにお尻が揃わないから気持ち悪い感ありつつ
Avatar
[ xxx , yyy , zzz ]` これはキモい
9:50 AM
構文として、1番目の要素を改行するのが自然か否かという問題がある
9:50 AM
あとスペースの有無かな
9:51 AM
そもそもArray, Dictionaryは確か、Swiftなら末尾のペアの後ろに,いてもコンパイラ許してくれない?
Avatar
ですね
9:52 AM
いちいち消すの面倒で全部つけてます
Avatar
ArrayやDictionaryとreturn whereの決定的な違いは、リテラルの開始が末尾とペアか、先頭にしか存在しないか
10:32 AM
というのがあるなーと朧気に考えていた
Avatar
omochimetaru 7/5/2017 1:30 AM
SPMでビルド済みのC static libraryをswiftとリンクする時に
1:30 AM
ソースツリーに配置したstatic libraryを相対パスで指定することってできますか?
1:30 AM

概要

Swiftがオープンソース化されると同時にSwift Package Manager(以下SPMと略記)も公開されました。...
1:31 AM
この記事の例だとシステムにインストールされた libhiredis をリンクしているようなんですが
1:31 AM
これをリポジトリローカルでやりたい
1:32 AM
module map の link 命令は -l オプションになるっぽいのです
1:34 AM
あ、 $ swift build-Xlinker があるな。
Avatar
omochimetaru 7/5/2017 5:15 AM
#swiftpm 作ったのわすれてた。
Avatar
#react-native#xamarin あるのを最初見て幅広くてびっくりしましたw
Avatar
omochimetaru 7/5/2017 5:33 AM
まだ発言が無いですね・・・
Avatar
Swift信者多めだから…
Avatar
Swift で書ける Xamarin 的なものほしいですね。
Avatar
C#がイケてるから技術的には可能そうですよね
Avatar
技術的には可能でしょうが、メンテするのがきつそうですね😅
9:06 AM
それこそマイクロソフトくらい体力のある企業ならできるんでしょうが・・・。
Avatar
JNI通したwrapperを毎回APIに合わせて実装してるってことですもんね
9:07 AM
常軌を逸している...
Avatar
機械的にやってるのかもですが、言語的な差異もあるし難しそうですよね。人手だと気が狂いそう・・・
9:10 AM
アップルがやっても Android を利するだけでしょうし期待薄ですね・・・。 Chris Lattner がマイクロソフト入りで Xamarin が Swift 化とかに 1% くらい期待できそう?
Avatar
1%高すぎでは
Avatar
Avatar
Xamarinじゃないにしても、UIKitはいい加減しんどいので純正Swift UI Framework出して全てを灰燼に帰してほしい
Avatar
Xamarin はともかく、マイクロソフト入くらいなら 1% くらいあるかも?
9:11 AM
純正Swift UI Framework出して全てを灰燼に帰してほしい
ほんとそれですね。
9:12 AM
来年の WWDC とかでそれ発表されたらめちゃくちゃ盛り上がりますね。
Avatar
今年のWWDC予想は見事に現実路線だったので(名前はiXXではなかったけど)
Avatar
omochimetaru 7/5/2017 9:13 AM
OS X 10.10.3にUIKit風のAPIを提供する新UXKitフレームワークの存在が明らかに https://www.infoq.com/jp/news/2015/03/apple-uxkit-framework-found#.WVytuvFWauU.twitter
最近OS X 10.10.3ベータで見つかったUXKitフレームワークが,あちらこちらで話題になっている。興味深いのは,APIがiOS UIKitのものに酷似していることだ。ここから一部の開発者たちは,これら2つのプラットフォームを近付けることができるのではないか,と期待している。
9:13 AM
これが気になってる
9:13 AM
UXKitがFullSwift, iOS / MacOS クロスだったら嬉しい
Avatar
UXKit、Photosがそれじゃなかったっけ
9:14 AM
大分昔の話
Avatar
omochimetaru 7/5/2017 9:14 AM
フム
Avatar
Swiftより前だよ確か
Avatar
omochimetaru 7/5/2017 9:15 AM
じゃあ駄目かも
Avatar
Swift UI Framework はアップルにもメリットがあると思うのでやってほしい・・・
Avatar
norio_nomura 7/5/2017 12:14 PM
ABIが安定するまで当分は期待できないと思うな。
Avatar
たしかに。
12:49 PM
iOSに同梱して配布はできないんでしょうか?
Avatar
古いOSがswiftのライフサイクルで切り捨てられる世界観にw
1:19 PM
それはそれで良いと思うけど(過激派)
Avatar
ああ、確かにそうですねw
Avatar
Range の包含関係を調べたくて↓こんな不毛なものを作ることになってしまったんですが、何か良い方法はないでしょうか。 https://gist.github.com/koher/5fd8f29a99de47457431cded99987d4f
Avatar
Range絡みは僕もベストプラクティスをしりたいです。Swift4 で one sided も入ってくるからもっと複雑になりそうですしね。
😂 1
Avatar
omochimetaru 7/6/2017 11:05 AM
Swiftコンパイラ開発環境構築 by @rintaro on @Qiita http://qiita.com/rintaro/items/2047a9b88d9249459d9a
Swift がオープンソースになってしばらく経ちます。 コンパイラや標準ライブラリの開発に手を出してみたいけど、リポジトリを落とした後どうしていいかわからない!という方のために、まずは開発環境の構築方法をご紹介します。基本的には[RE...
11:05 AM
すばらしい!!!
Avatar
ありがとございまーす😅
💕 1
Avatar
間違えた
Avatar
norio_nomura 7/6/2017 12:07 PM
ビルドディレクトリにどれくらい容量が必要か?とかの情報もあると良さげ。
👍 1
Avatar
norio_nomura 7/6/2017 12:15 PM
build-toolchain は30GB超だったかな
Avatar
やべぇw足りないw
Avatar
34G ですねー。 build-toolchain は本当に必要ないですよ。
Avatar
norio_nomura 7/6/2017 12:18 PM
最近触ってたswift-corelibs-foundationのテストは3.33GBで済んでる
Avatar
build-script -R なら 3G くらい。リポジトリ自体は 4G ちょっとなので、10Gあればなんとか・・・
Avatar
掃除するか…
Avatar
norio_nomura 7/6/2017 12:23 PM
linuxビルドするためのdocker imageが831MB
12:26 PM
linuxビルドはメモリ1GBだと途中で落ちる。2GBだとリリースビルドが通る。
12:27 PM
macOSだとそんな制限はなさそう。
Avatar
あ、間違えてたリポジトリ自体は 2G 無いくらいでした。
Avatar
追加しました!
👍 1
Avatar
norio_nomura 7/6/2017 12:53 PM
LinuxにSourceKitを標準で含める様にできてから自分でpackage buildする理由がなくなった。 (edited)
Avatar
あーなるほど。SourceKitはあまり触ってないので、意識したことなかったです。
Avatar
norio_nomura 7/10/2017 3:41 AM
👏 2
😇 1
Avatar
omochimetaru 7/10/2017 3:51 AM
ちゃんとメール出して偉いしstdlibを引き合いに出して説得力を増してるところがさすが @rintaro というかんじで素晴らしい・・・
3:52 AM
stdlibだけはアンスコ付きだとユーザから情報拾えなくなるの利用して、既存をエイリアスにしつつdeprecated貼って、エイリアス先のアンスコ付きを内部で使ってるんですねえ
Avatar
姑息としか言い様がないw
Avatar
omochimetaru 7/10/2017 3:57 AM
stdlibだからこそ特別にやっていいことはできるだけ減らしていって、ユーザコードと同じように書かれているべきだと思います。最初は実装優先でそういうのもあっていいと思うけど、こうやって少しずつきれいな仕様に差し替えていけるとよい (edited)
👍 1
Avatar
そういうの、最近の出来事でReactiveSwiftとかNimbleのアップデートであったら便利だなという気持ちになりました
Avatar
SE–0110 has been modified to allow cases for closures that were accepted in earlier versions of Swift, as described in this email announcement.
😋 2
Avatar
swift-evolution で guard / catch が提案されてる。 guard let foo = try bar() catch let error { ... } // ここで foo を使う https://gist.github.com/khanlou/8bd9c6f46e2b3d94f0e9f037c775f5b9
2:34 AM
ネストしたくなく気持ちはわかる。けど、 guard let の意味が変わってしまうと過去に Chris Lattner がつっこんでる。
Avatar
omochimetaru 7/11/2017 2:36 AM
これってcatchした場合必ず脱出するんですよね? それならそもそもcatchしなければ良さそうだけど、エラーを包み直したいってことですか?
Avatar
いや、 return とかで早期脱出する場合です。
Avatar
omochimetaru 7/11/2017 2:37 AM
func nonThrowingFunction() { guard let value = try throwingFunction() catch { // handle `error` here, then leave scope print(error) // for example return } // use `value` here }
Avatar
try? だとエラー情報が欠落するからそれを使いたいって話ですかね
Avatar
guard let foo = try bar() が自然とみんなが思い浮かべるのは、多くの人が Optionalthrows の類似性があることを感じ取ってるからと思われておもしろい。結局前の Simple domain error はいるのかみたいなところと通ずるものがある。
Avatar
omochimetaru 7/11/2017 2:38 AM
あー thorws が無いから 再スロー できないのか。 (edited)
Avatar
@t.ae うん、そうだと思う。
2:39 AM
今だと、 let foo: Foo do { foo = try babr() } catch { ... }
2:39 AM
で同じことができる。
Avatar
omochimetaru 7/11/2017 2:39 AM
その関数としてエラーを伝搬する気が無い時点で欠落も何もって感じがするけどなあ 例だと print してるけど。
Avatar
guard の脱出強制がないだけですね
Avatar
だね。あと書くのが少し面倒。
2:40 AM
その関数としてエラーを伝搬する気が無い時点で欠落も何も
エラーの種類で return する値を変えたいとか。
Avatar
Error捕まえてどうしたいんだろう、別のErrorで包むのかな
Avatar
omochimetaru 7/11/2017 2:41 AM
うーむ。それなら最初から下請けの関数が enum で返しとけと思うが、まあありえるか。
Avatar
Swift から外のシステムにつなぎこむときにエラーの種類に応じたエラーコードを整数で返さないといけなくて
Avatar
omochimetaru 7/11/2017 2:41 AM
型無しエラーから型有りの何かへの昇格したい場合かつ早期脱出・・・
Avatar
guard 内があんまり複雑になるなら現状のtry catchのほうが良いかなぁと思わなくもない。 (edited)
Avatar
エラーが発生したらエラーの種類に応じたエラーコードで早期脱出とか?
Avatar
omochimetaru 7/11/2017 2:42 AM
でも、脱出しない場合が許されないわけですよね
Avatar
脱出したい場合の話をしてるんじゃない?
Avatar
omochimetaru 7/11/2017 2:42 AM
とっつきにくい感じがする
Avatar
早期脱出してネストを避けたい。
Avatar
omochimetaru 7/11/2017 2:43 AM
あんまり入ってほしくないなあ・・・ catch と else が並ぶのもよくわからないし・・・
Avatar
例えば、この種の処理が複数発生すると、 do / catch をネストするか、まとめて処理するか、↑に書いたみたいに let foo: Foo に後から代入するか
Avatar
omochimetaru 7/11/2017 2:44 AM
↑の let あとから代入が良さそうだけどあれか、型かかなきゃいけないのか
Avatar
Optionalとthrowsの類似性はまあわかるけど、
Avatar
だけど、手軽に早期脱出パターンを書きたいというのはわからんでもない。
Avatar
try catchの場合は外側に変数定義してやるからネストはguardと同等ですよね。 そこのネストが問題ならdo内で余計なことをやりすぎてることになる。
Avatar
@omochimetaru うん、型書くの面倒だし、行が増える・・・。
2:44 AM
でも、 Chris Lattner の言うように guard let foo = try bar() はないから
2:44 AM
それだとうまい構文が作れなさそうだから
Avatar
tagged unionとuntagged unionって型自体が違うし
Avatar
やっぱ let foo: Foo に後から代入しか仕方ないと思う。
2:46 AM
tagged unionとuntagged unionって型自体が違うし
throwsResult<T, E> と等価で Optional<T> と同様 tagged union じゃないですか?
Avatar
throwsのままだとuntaggedですよね
Avatar
omochimetaru 7/11/2017 2:46 AM
いや
Avatar
guardifの内と外が入れ替わったようなものですけど trycatchが強制されているというのもあるか
Avatar
omochimetaru 7/11/2017 2:46 AM
f() throws -> ErrorType これが書けるから Tagged だよ
2:47 AM
Untagged Union は 同じ型をくっつけたときにどっちがわかわからないデータ構造
Avatar
あー
Avatar
omochimetaru 7/11/2017 2:47 AM
throwsのエラー側と、返り値側は常に区別されているから Tagged
Avatar
でも、Result<T,Error>だとして
2:49 AM
Result<Result<T,Error>,Error>これは表現できない
Avatar
omochimetaru 7/11/2017 2:49 AM
あ、たしかに。
Avatar
必ずResult<T,Error>になるよ
Avatar
omochimetaru 7/11/2017 2:49 AM
Tagged Union でも無いね。
2:49 AM
Tagged Union 未満の特別存在だ
Avatar
@t.ae do { let foo = try getFoo() do { let bar = try foo.bar() // bar を使う処理 } catch { retirm 98 } } catch { return 99 } ↑を避けて
2:50 AM
guard let foo = try getFoo() catch { return 99 } guard let bar = try foo.babr() catch { return 98 } // bar を使う処理 にしたいということかと。 (edited)
Avatar
そもそも内側のdoは外側のdo内に入れるべきなのか (edited)
Avatar
でもエラーの種類で区別できるとは限らない。
Avatar
簡易構文があったほうがいいというのは賛成ですね
Avatar
koherさんの例でしたら guard let foo = try? getFoo() else {return 99} で表現できそうな…?
Avatar
@tarunon ネストは func foo() throws -> () throws -> Foo { ... } ですね。
Avatar
そもそもthrowsのデザインがErrorの種類で分別するのが前提なので
Avatar
@lovee たしかに。 catch でエラーの種類で分岐しないとですね。
Avatar
分別できないようなのはtry?でOptionalの括りにしても問題はないのでは、という気がする
Avatar
guard let foo = try getFoo() catch let error { switch error { // } } という感じですかね? (edited)
Avatar
エラー分岐について二つの話が混ざってますが、↑の getFoofoo.bar については
Avatar
@lovee それだとネストが深くできるからcatchの段階で分別できたほうがよさそうですね (edited)
2:55 AM
現行のdo catchと同じように
Avatar
guard let foo = try getFoo() catch let error as QuxError { return 98 } catch { return 99 } guard let bar = try foo.bar() catch let error as QuxError { return 97 } catch { return 99 } // bar を使う処理 (edited)
Avatar
やっぱりなんかこう行数がおおいと外側に変数定義する一行が増えるくらい大したこと無い気が
Avatar
のように getFoofoo.bar が同じエラーを返す場合がまとめて catch では分岐できない。
Avatar
いや代入部含めて二行増えるか (edited)
Avatar
omochimetaru 7/11/2017 2:58 AM
あれ?それって return 98 の行に入るのはどういうときですか?
2:58 AM
ああ、catchの型でわけてるのか
Avatar
どっちかと言えば発生したErrorをその行で別のErrorにラップできる構文が欲しいんじゃないのかな
Avatar
書いてて思ったけど、エラーの種類で分岐よりも try? で困るのは、 catch で logger にログを書き出したいとかかなぁ。
2:59 AM
@tarunon エラーラップ構文はほしいですね。今は Typed Throws がないからルーズに素通しできるけど、 Typed Throws を導入するならラップしなおす簡単な構文がほしいです。
Avatar
それがあれば、guard catchは要らなくなるかと。
Avatar
本質的には Typed Throws があろうがなかろうが適切にラップしなおすべきだけど。
Avatar
勿論guard catchがその機能を内包しても良いんだけど
Avatar
guard catch はラップしなおしに限らないと思います。 return もあるし。
Avatar
内包するという話
Avatar
ただ、結局 guard let は Optional binding に割り当てられてて今の構文とマッチしないから
3:01 AM
guard let foo = try getFooOpt() // ??
Avatar
omochimetaru 7/11/2017 3:02 AM
↑それは今もできませんか?
3:02 AM
例外が飛んだら吹っ飛んでそれを包む関数自体が例外を投げる
Avatar
do { guard try ... catch { //ここでthrowして } ... } catch { //ここで受け取る }
Avatar
この構文はなくて、他にいい構文も思いつかないから、早期脱出したければ let foo: Foo do { foo = try getFoo() } catch { ... } しかないと思う。
3:03 AM
↑それは今もできませんか?
今もできるから問題で、 Optional binding なのか guard / catch なのか曖昧になるから
3:04 AM
guard / catch は構文としてあり得ないという話。
3:04 AM
throws な関数をコールするときにバインドしながら早期脱出したいニーズ自体は理解できるけど、ここで提案されてる構文はあり得ない。
Avatar
omochimetaru 7/11/2017 3:05 AM
catch がついてるかどうかで決まる話してるのかと思っていました。
3:06 AM
catchがついてた場合に Optional剥がしも同時に起きるのか Error剥がしだけが起きるのかはよくわかっていなかった。わかりにくいのはそうですね。
Avatar
現状↓なら型を書くくらいの面倒さで済む? let foo: Foo; do { foo = try getFoo() } catch { return }
3:07 AM
可読性低そう・・・
Avatar
omochimetaru 7/11/2017 3:07 AM
てかほんとうは
3:07 AM
その型省略できてほしいなあ
Avatar
あと catch の中に returnthrow が強制されていないのが問題なんじゃないですかね?ここでの問題点として
Avatar
guard let foo = try getFoo() catch { return }
Avatar
いやその文でcatch分岐しないといみないのでは
Avatar
omochimetaru 7/11/2017 3:08 AM
後続の単一の代入文の紐付けがされてるわけだから推論できる
Avatar
並べるとやっぱ可読性は違うなぁ。
Avatar
結局 do catch スコープの場合は catch 以降のコードも実行されることが予想されているので…
Avatar
omochimetaru 7/11/2017 3:08 AM
@lovee そもそもそうですね。
Avatar
その型省略できてほしいなあ
それは思うけど Swift の型推論がこれ以上複雑なことしたら大変なことになりそう・・・。
Avatar
omochimetaru 7/11/2017 3:08 AM
ああそうか
3:09 AM
let foo: Foo; do { foo = try getFoo() } catch { return }
3:09 AM
これってちゃんと解析してくれるんだっけ?
3:09 AM
catchの中の return を見て、以降の fooの初期化漏れが無い事をコンパイラが理解するか
Avatar
REPL 通ったことを確認済み。
Avatar
omochimetaru 7/11/2017 3:09 AM
なるほど。
Avatar
うん。そこは大丈夫
3:12 AM
@lovee 早期脱出が強制されるのはそこまで重要じゃない気がするんですよね。早期脱出したい人は結局早期脱出するだろうし。まあ return の書き忘れくらいはあるかもですが。
Avatar
omochimetaru 7/11/2017 3:13 AM
@koher いや、そこは書く人じゃなくて読む人のための機能だと思います
Avatar
return してればフロー解析で foo は使えるし。
Avatar
omochimetaru 7/11/2017 3:13 AM
書くときに自分のためにguard書いたことない else でわかりにくいし
Avatar
@omochimetaru 可読性が劣っているのは間違いない。
Avatar
do let x = try ... catch {} でいいんじゃないの
3:14 AM
doの括弧がしんどいだけで、これをワンライナー許せば解決できそう
Avatar
@tarunon それは Swift が式指向の言語にならないときつそうじゃないですか?
3:14 AM
それを認めだしたら if も値がほしいですし
Avatar
omochimetaru 7/11/2017 3:14 AM
doをオペレータにしたいってのはありそうな気がする
Avatar
そうするとラムダ式と return の関係とかも見直さないと一貫性がないし
3:15 AM
(他の言語みたいに最後の式の値を戻り値として採用するのかどうか)
3:15 AM
doif の中には return は明示的に書けないから(外の関数の return になっちゃう)
Avatar
omochimetaru 7/11/2017 3:15 AM
doスコープのなかのtryが全部一箇所にcatchに飛んでくるけど、一個ずつ丁寧にcatchして処理を分けたい場合に
Avatar
いやこれはguardが被ってるからdoに変えただけで、式の機能は有していない
Avatar
最後の式の値を採用するしかない。
3:16 AM
ああ、 do let なのか
Avatar
omochimetaru 7/11/2017 3:16 AM
たしかに let とかもスコープを伴わないけど式ではないね
3:16 AM
do から始まる文をかけたらいいってことよね
Avatar
そう、catch句は脱出強制になる
Avatar
意味的に guard だから guard じゃないものにそれを負わせるのはややこしいと思うんですよねぇ。
Avatar
ですね、多分単語の意味合い的には guard は早期脱出を伴うことを教えてくれてるという意味合いがあると思います
Avatar
まあぶっちゃけそこまで頻度高くなさそうだし、 guard let foo = try? getFoo() else { return } で大体は代用できそう。 (edited)
Avatar
omochimetaru 7/11/2017 3:18 AM
そうですね 僕はほとんどのケースがそれで済むと思っていて 「再スローしない関数でcatchでわけて脱出したい」っていう前提のストーリーが狭すぎると思う
Avatar
どうしてもエラーがほしかったら let foo: Foo do { foo = try? get Foo() } catch let error { logger.log(error); return }
Avatar
どうしても do catch のネストが深くなりそうならもういっそのことメソッドを出してあげるのも一つの手段ですかね
Avatar
omochimetaru 7/11/2017 3:19 AM
そのレアケースのために構文がひとつ複雑化するのは割にあわないと思う・・
Avatar
@lovee そうですね。細かく関数/メソッドに切り出すのもいいと思います。
Avatar
@koher 本当そうですね…(会社の数百行を及ぶC++の関数を眺めながら(白目 (edited)
😨 1
Avatar
@lovee @mono さんが前に挙げてた、関数は 6 行(?)以内におさまるように分割すべし、みたいな考え方、現実的には難しいケースも多いけど常に心がける価値はあると思っています。と言いつつも僕も実際のコードは長すぎてぐちゃぐちゃだったりしますが・・・。
3:23 AM
細かく分割するとテストを書きやすくて、テストを書くと結局最終的にバグの発見が早くて時間的にペイすると思うんですよね。
Avatar
omochimetaru 7/11/2017 3:24 AM
コード片のモジュール性があがるんで変更にも強くなりますね
Avatar
特に&&||! を使った条件とか書いた瞬間に、そこだけでもテストしたい。
3:24 AM
そこで、いちいちテストのファイルに飛んで関数切って、とかじゃなくて
Avatar
omochimetaru 7/11/2017 3:24 AM
300行の関数で299行目に参照する変数が1行目に宣言されてたらもうその300行を分割するのは無理
Avatar
if 文に直接テスト書き足せたりするとうれしい。
Avatar
中間を切り出すことはできるのでは?
Avatar
299行目に参照する変数が1行目に宣言されてたら
2 行目から 298 行目が関数になるのでは?
Avatar
omochimetaru 7/11/2017 3:27 AM
その間の298行の間にその変数が参照されていないことを確認しないといけない
Avatar
必要なら関数の引数にするんじゃない?
3:27 AM
引数にしなかったらコンパイルエラーになるから必要なことに気づけるし。
Avatar
omochimetaru 7/11/2017 3:28 AM
はい、で、だいたいは、135行目でも何かが代入されていて (edited)
3:28 AM
その右辺値の式に別の変数や関数呼び出しが出てくるので
3:28 AM
どんどん芋づる式にデータフローの依存関係をたぐっていって
Avatar
inout 関数や
Avatar
omochimetaru 7/11/2017 3:28 AM
その300行のデータ依存関係を完全に解析してはじめて
3:29 AM
やっとこさどこがロジックとして分割可能か判断できる
Avatar
ああ、そういう意味で後から分割する大変さのことを言ってるのか。
Avatar
omochimetaru 7/11/2017 3:29 AM
300行書き下すときは、書いてる本人は、気にする部分だけ気にしながら書き下すから簡単だけど
3:29 AM
読みとく側は無限の可能性のツリーを絞り込みながらデータフローを再構築しないといけないから
3:30 AM
めちゃくちゃ手間がかかる。
Avatar
ローカル関数がもっと書きやすくて、テストしやすかったら分割もしやすいと思うんだよなぁ。
Avatar
omochimetaru 7/11/2017 3:30 AM
クラスのメソッドはクラスというスコープでフラットに散らかってしまうという問題があって
Avatar
うん。
Avatar
omochimetaru 7/11/2017 3:30 AM
メソッド同士の依存関係のレイヤーで同じ解析が必要になるから
3:31 AM
型を切る話が出てくるけど、ローカル関数をつかって
3:31 AM
それをできますね。
Avatar
ローカル関数にするとローカル変数をキャプチャしてしまう問題とテストできない問題がある。
Avatar
omochimetaru 7/11/2017 3:31 AM
ローカル関数はそれを参照する範囲がクラスより狭くなるのが良い。
3:31 AM
そうですねー
Avatar
今整理のために階層を切りたいだけで、本当にやりたいことはローカル関数じゃないから。
Avatar
omochimetaru 7/11/2017 3:31 AM
nested classがやっぱりバランスいい事が多いと思う
3:32 AM
僕はときどき「struct ComputeXxxWork」みたいに
Avatar
処理フローもわかりにくくなると思うんよね。
Avatar
omochimetaru 7/11/2017 3:32 AM
型を切り出してます
3:32 AM
そうするとこの構造体から、outer classのメソッドには依存しないことを保証できるからいくらか解析しやすくなる
Avatar
func foo() -> Foo { let bar: Bar do { // bar を組み立てる処理 ... } let baz: Baz do { // baz を組み立てる処理 ... } let qux: Qux do { // qux を組み立てる処理 ... } return Foo(bar, baz, qux) }
3:33 AM
Avatar
参照範囲で思ったのは、Swift 4でprivateが同じファイル内の同じクラスで参照可能になったのがある意味改悪な気が…
Avatar
omochimetaru 7/11/2017 3:34 AM
@lovee 同じ型名のextensionからだけじゃなかったっけ
Avatar
@omochimetaru そうです
3:35 AM
ようは何が言いたいかというと、今まではこの extension 内のみで参照可能にしたいやつをたくさん作ってきたので()
Avatar
func foo() -> Foo { let bar = foo_bar() let baz = foo_baz() let qux = foo_qux() return Foo(bar, baz, qux) } func foo_bar() -> Bar { ... } func foo_baz() -> Baz { ... } func foo_qux() -> Qux { ... }
3:35 AM
だと、前者の方が流れが読みやすいと思う。
3:35 AM
そんなことないかなぁ。
Avatar
omochimetaru 7/11/2017 3:35 AM
@koher そうですね、それだとfooは読みやすくなるけど foo_barが他のところに露出してる問題がある
3:35 AM
foo_barのメンテナンスを考えた時、それを変更してもよいかどうか検証しないといけなくなってる
Avatar
foo がやりたいことは読みやすいか。
3:36 AM
この foo_bar とかをわかりやすく foo に関連付けて分離できる仕組みと、
3:36 AM
書くときに分離する手間を軽減できれば良さそう。
Avatar
omochimetaru 7/11/2017 3:36 AM
なので・・・ sturct FooConstructWork { func construct() -> Foo private func createBar() -> Bar private func createBaz() -> Baz private func createQux() -> Qux }
3:36 AM
とやれば、いいとこどりかなと
Avatar
foo がメソッドで、インスタンスのプロパティを使いたいときは?
Avatar
omochimetaru 7/11/2017 3:37 AM
FooConstructWork::createBar() の変更のときに気をつける行数は FooConstructWork の中身全部を読めばいいけどそれはもともとの foo と同じ量ですむ
Avatar
structinit に渡す?
Avatar
omochimetaru 7/11/2017 3:37 AM
その場合は、依存する入出力を FooConstructWorkのAPIとして定義する
3:38 AM
initで受けて、返り値を struct FooConstructWork::Result っていうさらなるnested typeにして
3:38 AM
もともとの fooをイカのように書き直す func foo() { let work = FooConstructWork ( depends_field1, depends_field2 ) let ret = work.construct() self.depende_fields3 = ret.field3 } (edited)
Avatar
これ徹底しようとしたら、ほとんどのメソッドが struct になっちゃったりして萎えないかなぁ。
Avatar
omochimetaru 7/11/2017 3:39 AM
これやるとfooの中で変化しうるフィールドがひと目で確認できるのもよいですね。
3:39 AM
いや、メソッド自体は残しておいて
3:39 AM
その中でstruct使えばいいので。
Avatar
struct にしてるから、状態変化する変数をプロパティで表せるのか。
Avatar
omochimetaru 7/11/2017 3:41 AM
あ、そうです。
Avatar
いいかも。
Avatar
omochimetaru 7/11/2017 3:41 AM
関数の中で作業用につかうvarはフィールドにして
3:41 AM
メソッド間で共有変更します
Avatar
イニシャライザ、 construct については一行で書けるし
3:42 AM
元のメソッドとの間で命名規則を決めておけばよさそう。
Avatar
omochimetaru 7/11/2017 3:42 AM
返り値を構造体で戻して、(つまりnominal tupleですね) それをcallerのフィールドに明示的に差し戻す
Avatar
construct 長いし make とかがいいかな。 func foo() -> Foo に対して struct MakeFoo とか?
3:43 AM
でも任意の関数で考えたら必ずしも作るとは限らない。
Avatar
omochimetaru 7/11/2017 3:44 AM
まあそこは別に読むときに辿っていけば読めるので
Avatar
func foo(x: Int) { RunFoo(zelf: self, x: x).run() } struct RunFoo { private let zelf: ... private let x: Int func run() { ... } ... } (edited)
Avatar
omochimetaru 7/11/2017 3:44 AM
もともとのたどる範囲が広すぎる問題を解決してる事が大きい
3:46 AM
self渡しちゃうとなんでも変更されうるのでつらいですよ
3:47 AM
innner classじゃなければ private は触られないからもともとのメソッドよりマシだけど
Avatar
うーん、でも重度に外部のプロパティに依存してるケースもあるしなぁ。 (edited)
3:48 AM
引数に 20 個渡すとか死んじゃう・・・
Avatar
そこまでいくと分離するべきでないのでは
3:48 AM
もしくは更に細かく分離するか
Avatar
omochimetaru 7/11/2017 3:48 AM
20個渡してる場面では20個を5個ずつの型4ことかに整理できそう。
3:49 AM
もし分割できないのであればそれは本当に複雑なロジックってことなんで諦めるしかない
3:49 AM
大事なのは本当には複雑ではないロジックを複雑なコードにしてしまうケースをシンプルで読み解きやすいコードで表現することで
3:49 AM
本当に複雑なロジックは複雑なコードになることは避けられないと思う
3:50 AM
コロモゴロフ複雑性よりはわかりやすくできない
Avatar
20個渡してる場面では20個を5個ずつの型4ことかに整理できそう。
UIViewController とか(自作でない巨大な型)の場合は?整理して返すプロパティを生やす?
(edited)
Avatar
omochimetaru 7/11/2017 3:52 AM
ですね。本当に20個in/outしてるシーンは少ないと思います。 そのWorkの中で使うメソッドは、initializederでクロージャ受け取るようにしておくと
3:52 AM
使うメソッドも表明できます
3:53 AM
プロパティで戻さなくても例えば・・・
3:55 AM
FooWork ( getUserName: { return self.user.name }, setLabel: { self.label.text = $0 }, setImage: { self.imageView.image = $0 } ) , present: { self.presentViewController($0} )
3:55 AM
こういう感じにすると、UIViewControllerの中で、FooWorkによって起こる副作用のバリエーションを
3:55 AM
使うところで表明できる
3:55 AM
selfを渡すよりはぐっと絞り込まれる。
3:56 AM
まああとはそもそも複数のViewの塊をcomponentとして切るとかもできる事が多そう
Avatar
self が値型の場合は?
Avatar
omochimetaru 7/11/2017 4:01 AM
というと?
4:01 AM
同じようにキャプチャしてメソッド呼び出しもできるような。
Avatar
値型で let で受けておくと副作用がない
Avatar
omochimetaru 7/11/2017 4:03 AM
それならそもそもだいぶマシですね
4:04 AM
FooWorkの中から書き換えられることがないわけだし
4:04 AM
FooWork::Result から結果を書き戻すコードが絶対必要になるから
4:05 AM
そこだけ見ればデータフローが全部見通せる状態にできる
Avatar
議論追えてないですが、上のほうで @koher が記述してた do {} catch {} のネストは バグ有りなので、少なくとも現状やらない方が安全です。 https://bugs.swift.org/browse/SR-5339
Avatar
バグってるのかw
4:53 AM
あー
4:54 AM
なんかネストさせたときに変なところにError飛んで困ったことあったけどそれかな
Avatar
まさかそんなことがw
Avatar
あ、 catch 内に do を書くときだけか。 do { do { は大丈夫かも
4:56 AM
do { } catch { do { throw } catch { } } で内側の catch が呼ばれずに下まで抜けてしまうっていう問題だったと記憶してます。 (edited)
😳 1
Avatar
まさにそれ踏んでました。
4:56 AM
どこだったかな
4:57 AM
Hiyoko - http://www.hiyoko.co.jp, It's a sweets in Fukuoka. But this repo maybe become twitter app for iOS.
4:58 AM
ここで素直にthrowしようとすると変なことになって死んだ
😢 2
Avatar
↑確か、内側のcatchは内側doのtryのErrorを捕まえるはずだが、throwのErrorも捕まえてこの野郎!ってなった記憶がある (edited)
3:27 PM
そもそもdo内でthrowしたものはcatchに行くのが正?
Avatar
do内でthrowしたものはcatchに行くのが正?
これはそうだと思います。 SR-5339 素直にやると再現しないので、書かれている通り Swift ではなく Foundation の問題みたいですね。
Avatar
#swiftpm から。 これ知りませんでした。
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 7/12/2017 1:43 AM
↑読んだ記憶はあった
1:43 AM
順番入れ替えが一部できるのはキモいみたいな話
Avatar
なんか struct のデフォルトの init だとできるとかなかったっけ??
Avatar
ラベルが強制されてる分kotlinとかよりは良さそうな気が
Avatar
Swift の命名ともマッチしないし、引数が多くなると型でまとめるが正しいアプローチなのかな。
1:44 AM
昨日の、引数 20 個とかとも通ずる話な気が。
Avatar
そもそもkotlinが引数入れ替えできたか覚えていなかった pythonほ引き合いに出すほうが良かったですね
Avatar
omochimetaru 7/12/2017 1:45 AM
pythonは辞書じゃなかったっけ
1:46 AM
rubyもそう
Avatar
引数が多いと順番わからなくなる→引数が多すぎることが原因→型でまとめれば良い
Avatar
辞書じゃないのも指定できるっぽいです
1:46 AM
In [4]: def hoge(a, b): ...: print(a, b) ...: In [5]: hoge(a=1, b=2) 1 2 In [6]: hoge(b=2, a=1) 1 2 (edited)
Avatar
omochimetaru 7/12/2017 1:46 AM
@koher 思ったんですけど、普段はxcodeがひな形出してくれるから順番は覚えて無くても困らない
Avatar
Foo([ \.name: "Jason" \.age: 20 ]) みたいなのが型安全でできればいいな、と。
Avatar
omochimetaru 7/12/2017 1:47 AM
@t.ae じゃあ常にラベル付け呼び出しもできるのかw
Avatar
kotlinは引数入れ替え出来た気がする
Avatar
↓と並び替えは相性悪そう。 func foo(a: Int, a b: Int, a c: Int) -> Int { return a + b + c } foo(a: 2, a: 3, a: 5)
Avatar
ラベルが被ることがあるのか。
Avatar
そもそもメソッドの命名が
Avatar
omochimetaru 7/12/2017 1:49 AM
swiftってラベルかぶり許されてたのか
Avatar
func foo(with x: X, with y: Y) みたいなのが有り得るから
Avatar
ラベル周りの複雑さは Swift にとってネガティブ要因だと思う。 Obj-C に引っ張られすぎ・・・。 (edited)
Avatar
omochimetaru 7/12/2017 1:51 AM
そうですかねえ
1:51 AM
他の言語だと4引数ぐらいになってくるともう何渡してるかわからなくなるので
Avatar
Python くらいの感じがいいんじゃないかな。
1:51 AM
英語として読ませるのとかも無理が出て来るし・・・。
Avatar
omochimetaru 7/12/2017 1:51 AM
まあたしかに。pythonなら呼び出し側で明示できるから、いいのか。
Avatar
Python は Python で、 ラベル付けるのが正当なのか、フラットに渡すのが正当なのか迷うので、微妙なんですよね。
Avatar
omochimetaru 7/12/2017 1:53 AM
なるほど
Avatar
大半の言語がそうですけど関数呼び出しでどの引数が何なのか一見で分からないのはストレスになりますね。swift慣れしすぎたんでしょうが
Avatar
omochimetaru 7/12/2017 1:53 AM
そう。そのストレスすごいわかる。
1:53 AM
ラベル付けする代わりに、ローカル変数で一回組み立てて変数名をラベルの代わりにしたりしてるよ。
Avatar
書くときは面倒なのでラベルつけたくないけどあとで読み直すと分からないというのがよくある
Avatar
ラベル強制でもいいけど、ラベルの重複は認めない、順番は自由、英語として読ませない、くらいでよかった。
Avatar
ラベル付けする代わりに、ローカル変数で一回組み立てて変数名をラベルの代わりにしたりしてるよ。
これやればいいんですけどね
Avatar
omochimetaru 7/12/2017 1:54 AM
@t.ae 同じ関数を2回呼んでるときに詰む
Avatar
あーpythonスコープきれないから・・・
Avatar
omochimetaru 7/12/2017 1:55 AM
C++ならスコープ切れるんだけどしんどいんだよなあ ボコボコするし行数伸びるし
Avatar
まぁpython書く時は使い回し上等でやってるんですが
Avatar
omochimetaru 7/12/2017 1:56 AM
定数指向諦めちゃうよね
Avatar
>> ラベル付けする代わりに、ローカル変数で一回組み立てて変数名をラベルの代わりにしたりしてるよ。
これやればいいんですけどね
これはよくやる。引数たくさんあるときに、コール時に計算して渡すと可読性悪くなるし。
1:56 AM
そして、この場合、ラベルが冗長な感じに・・・。
Avatar
omochimetaru 7/12/2017 1:56 AM
swiftでやると2重になっちゃうのは確かに。
Avatar
Kotlin の run とか、無名スコープが戻り値を返すとかだとやりやすい。 // Kotlin val foo: Foo = run { val bar = ... // 複雑な計算 val baz = ... // 複雑な計算 val qux = ... // 複雑な計算 Foo(bar, baz, qux) }
Avatar
@koher これって、 bar baz quxは1行では済まない感じなんですかね
2:01 AM
var foo = Foo( bar: ... // 複雑な baz: ... qux: ... ) 大体いつもこう書いてる
2:02 AM
必要なら各パラメータでクロージャ立てればOKかなと (edited)
Avatar
無名スコープでネストすることを考えるとインデントも同じですよね
2:02 AM
ラベルがむちゃくちゃ長い時は分けたくなりますが
Avatar
omochimetaru 7/12/2017 2:02 AM
@tarunon 例えばbazの値の構築にbarの値を再利用する場合や、bazとquxで共通の途中計算値を使う場合に、それだと困る
Avatar
それは引数の設定間違ってないかw
Avatar
@tarunon ラベルがないとどの引数に何を渡しているのかがわからない→一度変数に代入すればわかる、という流れでの話でした。
Avatar
ああ、なるほど
Avatar
run があるとクロージャ代わりになるのは便利ですね。 let foo = { ... return Foo(...) }() let foo = run { ... return Foo(...) }
Avatar
前者これコンパイル通ります?
Avatar
Kotlin は run とか apply とか、 ?: return とか、そのあたりの小道具が便利なんですよねぇ。
Avatar
let foo: Foo にしておかないとしんどそう
Avatar
@tarunon その通りでした。
2:07 AM
すごい、コンパイラの気持ちがわかってるw
Avatar
omochimetaru 7/12/2017 2:07 AM
え、マジ??
2:08 AM
returnからクロージャの型わかんないの
Avatar
まあ、引数に渡すときは大丈夫そう。
Avatar
run作ればコンパイル通る気がしてきた
Avatar
1> struct Foo { 2. var a: Int 3. var b: String 4. } 5> let foo = { 6. let a = 42 7. let b = "xyz" 8. return Foo(a: a, b: b) 9. }() error: repl.swift:5:11: error: unable to infer complex closure return type; add explicit type to disambiguate let foo = { ^ () -> Foo in
2:09 AM
5> let foo: Foo = { 6. let a = 42 7. let b = "xyz" 8. return Foo(a: a, b: b) 9. }() foo: Foo = { a = 42 b = "xyz" }
2:09 AM
10> func bar(foo: Foo) {} 11> bar(foo: { 12. let a = 42 13. let b = "xyz" 14. return Foo(a: a, b: b) 15. }()) ↑OK (edited)
Avatar
Foo であることまではわかってるのか……
Avatar
omochimetaru 7/12/2017 2:10 AM
@tarunon すげえな・・・
Avatar
16> func run<T>(_ f: () -> T) -> T { return f() } 17> let foo2 = run { 18. let a = 42 19. let b = "xyz" 20. return Foo(a: a, b: b) 21. } error: repl.swift:17:16: error: unable to infer complex closure return type; add explicit type to disambiguate let foo2 = run { ^ () -> Foo in
2:11 AM
run もダメでした。
Avatar
あら…残念…
Avatar
わかっているけど明示しろってことですね。
Avatar
こういう型推論周り、できないのが仕様なのか実装の問題なのか・・・。
Avatar
クロージャに返り値以外で型の明示必要なのは
2:12 AM
lazy varとかで頻出な気がします
Avatar
omochimetaru 7/12/2017 2:13 AM
踏んだ時は明示してるんだけど、「ふざけんな」としか思ってないから
2:13 AM
どういうときにそうなるか身についてない
Avatar
お、 Kotlin だとできた。 data class Foo(val a: Int, val b: String) fun main(args: Array<String>) { val foo = run { val a = 42 val b = "xyz" Foo(a, b) } print(foo) } Foo(a=42, b=xyz)
Avatar
swiftもrunが1行ならいけるはず
2:46 AM
mapがOkでrunがダメなの解せないなー
Avatar
↓もいけた。 // Kotlin data class Foo(val a: Int, val b: String) fun main(args: Array<String>) { val foo = { val a = 42 val b = "xyz" Foo(a, b) }() print(foo) }
Avatar
omochimetaru 7/12/2017 2:47 AM
kotlinはわりと普通になんでもできて、swiftみたいなアレ??って事が起きないんですよね。
Avatar
その代わり、型推論があっさり諦めることも多い印象。
2:48 AM
Swift は「え?それもできんの?」って思うことと、「え?これもできないの?」って思うことがある。
Avatar
omochimetaru 7/12/2017 2:48 AM
ww
Avatar
アプリカティブの推論とかよくできてるなと思わない?
Avatar
omochimetaru 7/12/2017 2:49 AM
kotlinできないんでしたっけ?
Avatar
いや、 Kotlin でもできるけど、なんかできなくなる条件があったような・・・。
Avatar
omochimetaru 7/12/2017 2:50 AM
ふむ
2:50 AM
HM型推論を勉強・ちょっと実装した経験があるから
2:50 AM
直感的には、まあできるだろうって思う事が多い
2:51 AM
サブタイピングとかオーバーロードが絡んでるところはよくわからなくて、すごいって思うけど
2:51 AM
アプリカティブの連続適用とかはそういう意味では素直
Avatar
なんというか、ジェネリックな curry とジェネリックな戻り値型推論の組み合わせとか Swift でうまくいくイメージがわかないけどうまくいってる。
2:54 AM
Kotlin のアプリカティブは↓でうまくいってるけど、式を複雑にしたらダメだった気がする。 val person: Result<Person, JsonException> = curry(::Person) mp firstName ap lastName ap age https://github.com/qoncept/kotres
kotres - Provides the Result class for type-safe error handling in Kotlin
2:55 AM
Swift も <*> の数がある数を超えると急にダメになったような? (edited)
Avatar
omochimetaru 7/12/2017 2:55 AM
ジェネリクスも本質的には 左辺値の推論と同じなんだと思います
2:57 AM
let x = exp() の式を左から舐めていって x をpolytype で仮埋めしていて、それがexpとunificationされて確定することと
2:57 AM
exp( x: Box<Int> ) に makeEmptyBox() -> Box<T> をわたして exp ( makeEmptyBox() ) という形にときに
2:58 AM
makeEmptyBox() の型変数が Box < polytype > になっていて
2:58 AM
型パラメータ T が埋まっていない状態っていうのは
2:58 AM
推論機にとって、左辺値が不定な状態と同じ枠組み
2:58 AM
で扱える
2:59 AM
似たような話で C++14 が
2:59 AM
逆方向に話が展開しているのが面白くって
3:00 AM
いまは Swift において、 ジェネリック型は型推論の枠組みに収まるって言ったんですけど
3:00 AM
C++14 で、ラムダの引数の型を auto 型、つまり、推論させろっていう設定でラムダ式が書けるんですが (edited)
3:00 AM
ジェネリックラムダ(generic lambdas)は、C++11のラムダ式を拡張して、パラメータにテンプレートを使用できるようにした機能である。
Avatar
run のクロージャ式が 1 行だとたしかに通った。 @tarunon さんすごい・・・。 1> func run<T>(_ f: () -> T) -> T { return f() } 2> struct Foo { 3. var a: Int 4. var b: String 5. } 6> let foo = run { Foo(a: 42, b: "xyz") } foo: Foo = { a = 42 b = "xyz" }
Avatar
omochimetaru 7/12/2017 3:01 AM
これは逆に、ジェネリックラムダは、テンプレート機構とみなされる
3:01 AM
つまり、型推論のようなことをやらせるために、テンプレートを使う
3:02 AM
もちろん厳密にはテンプレートの型解決ルールはHM型推論よりは弱いのでC++だと苦労する場面はあるんですが、この挙動で結構、高階関数がちゃんと使える
Avatar
これって structural subtyping 的な考え方なのでは?
Avatar
omochimetaru 7/12/2017 3:02 AM
それて、テンプレートの型パラメータが決まってない状態で式展開していって、最終的に具象型で解決する処理の流れが、HM型推論がpolytypeで仮置きしながら推論を進めていく動きと、よく似ているなあと最近思った
Avatar
https://github.com/apple/swift/blob/master/docs/TypeChecker.rst
Swift limits the scope of type inference to a single expression or statement
推論を single expression closure までに絞っているのは一応はポリシーってことかと。
swift - The Swift Programming Language
Avatar
omochimetaru 7/12/2017 3:04 AM
structural subtyping の概念がわかってないからなんとも。あれってメンバのある無しを縛っていく話かと思ってました。
Avatar
おお、そうなんですねー。
3:06 AM
@omochimetaru ab の型は + できることから決まるという意味で。 (edited)
Avatar
omochimetaru 7/12/2017 3:07 AM
TypeChecker.rst今度読んでみよ
3:10 AM
@omochimetaru a と b の型は + できることから決まるという意味で。(編集済)
話のつながりがよくわからなかったです
Avatar
C++ のテンプレートと Swift のジェネリクスは、後者は型パラメータに制約を記述するして縛るという意味でちょっと違うような?ってこと。 (edited)
Avatar
omochimetaru 7/12/2017 3:14 AM
あーいま制約のことは置いていました
Avatar
Swift のジェネリクスとは関係なく C++ のジェネリックラムダが型を解決する仕組みが型推論と似てるって言ってるだけ?
Avatar
omochimetaru 7/12/2017 3:15 AM
Swiftの方は制約の無い struct A < T> を想定して考えていました。
3:16 AM
でも制約もオーバーロードされてなければ最後にチェックするだけだと思うんで
3:16 AM
あまり関係ない気がしますね
3:17 AM
つまり僕がいいたいのは
3:17 AM
Swiftの推論機がジェネリックな型パラメータを解決する部分は
3:17 AM
普通に左辺値の推論をするのと
3:17 AM
同程度の難易度のタスクだから
3:18 AM
そこができるからすごい、というふうには感じない、ということです
3:18 AM
C++の例は、型パラメータを解決する部分と左辺値推論が似ていることの補強のひとつです
3:19 AM
制約が満たされるかどうかの決定方法は C++ が Structural subtyping的で、Swiftが宣言的なのはそうだけど
3:19 AM
そこは推論フェーズには関係ないと思う。
3:19 AM
オーバーロードしたところで推論の道筋が分岐→1つのオーバーロードを仮定して推論を全部埋める→埋まったあとで、制約が満たされているかをチェックする→満たされていなければ次のオーバーロードを試す
3:20 AM
多分こういう挙動。で、制約が満たされているかをチェックする部分が、structural か、宣言的かは、「ジェネリックな型が推論に統合されている」話とは、別のフェーズで、どっちでもいい。
Avatar
まあ、そりゃできてるんだし本質的な難しさはないんだけど、もっと感情的に、 Swift の型推論は予想しないところでダメだったりする割に、 https://github.com/thoughtbot/Argo/blob/master/Sources/Argo/Types/Decoded/Applicative.swift#L18-L20https://github.com/thoughtbot/Curry/blob/master/Source/Curry.swifthttps://github.com/thoughtbot/Argo/blob/master/Sources/Argo/Operators/DecodeOperators.swift#L16-L18 みたいなのを複雑に組み合わせても意外とちゃんと動くんだなぁとおどろいたという気持ちです。
Argo - Functional JSON parsing library for Swift
Argo - Functional JSON parsing library for Swift
Curry - Swift implementations for function currying
Avatar
omochimetaru 7/12/2017 3:29 AM
なるほど。
3:29 AM
applicativeがすごく見えるのってすごい見せかけの問題って感じがする
3:29 AM
curry自体は curry ( function ) で完結するから簡単で
3:30 AM
<*> <| を展開して関数呼び出しに書き下せば
3:30 AM
納得というか。
3:30 AM
通してみると迫力はある。
Avatar
あとはアプリカティブに触れたのが左辺値型推論に慣れてない時期だったからというのもあるかも?
Avatar
今試したらmapもワンライナーじゃないとダメだった。
Avatar
ほんとだ。
3:42 AM
なんかおかしい気がする。
Avatar
omochimetaru 7/12/2017 3:44 AM
わりといつも1行で済ませられててあまり困ってないってことかね
3:44 AM
https://github.com/apple/swift/blob/master/docs/TypeChecker.rst > Swift limits the scope of type inference to a single expression or statement 推論を single expression closure までに絞っているのは一応はポリシーってことかと。
swift - The Swift Programming Language
3:45 AM
mapなんて死ぬほど使ってるのに、「え?そうだっけ?」感があるし。
今試したらmapもワンライナーじゃないとダメだった。
Avatar
実際にはですね
3:45 AM
map/flatMap/filter
3:46 AM
こいつらChainingで使ってるから、一番外側の左辺型から順番に伝播していて、書かなくてもなんとかなってるのでは、という気がしている
Avatar
最終的に左辺値の型が決まっているところに突っ込めればなんとかなりますね。
Avatar
func run<T>(_ f: () -> T) -> T { return f() } struct Foo { var a: Int var b: String } let foo = run { let a = 1, b = "str"; Foo(a: a, b: b) } これもいけたw
3:48 AM
これは 🤔 だな
Avatar
omochimetaru 7/12/2017 3:48 AM
えっ
3:49 AM
セミコロンつなぎだから single expression 扱いってこと?
Avatar
return がないから () -> () 扱い (edited)
Avatar
omochimetaru 7/12/2017 3:49 AM
邪悪な・・・w
Avatar
norio_nomura 7/12/2017 4:02 AM
warning出るね ⚠ Constant 'foo' inferred to have type '()', which may be unexpected
Avatar
Voidにしろ~ってやつかな
Avatar
omochimetaru 7/12/2017 4:03 AM
セミコロン区切り文の評価型は最後のセクションじゃなくて全体がVoid?
Avatar
ああ本当だ、Voidになってる
Avatar
return 書いたら Void じゃなくなるっぽいですよ
Avatar
return書いたら型を書けと怒られたw
4:06 AM
やはりここは protocol Factory の出番かな
4:06 AM
protocol Factory { init(_ f: () -> Self) } extension Factory { init(_ f: () -> Self) { self = f() } } extension Foo: Factory { } let foo = Foo { let a = 1 let b = "2" return Foo(a: a, b: b) }
4:06 AM
よさ味
Avatar
omochimetaru 7/12/2017 4:10 AM
Foo2回かいてるのが嫌
Avatar
その点はkotlinのapplyみたいのができれば良さそうですね
Avatar
omochimetaru 7/12/2017 4:11 AM
applyじゃmutableなクラスじゃないと駄目じゃない?
Avatar
そこがちょっと微妙なところですが
Avatar
@omochimetaru 減らしたで。 let foo = Foo { let a = 1 let b = "2" return .init(a: a, b: b) }
Avatar
omochimetaru 7/12/2017 4:11 AM
www
Avatar
文字数増えてる
Avatar
omochimetaru 7/12/2017 4:12 AM
これの本当に微妙なところは差し替えられるselfが実はallocだけされていること、であってるかしら
Avatar
ネームドタプルを返してイニシャライザ呼び出しは外でやらせれば
Avatar
そうだね > alloc
4:13 AM
ClassだとallocだけどStructはどうなんだろう?
Avatar
omochimetaru 7/12/2017 4:13 AM
structもallocだけなんじゃないかな
4:14 AM
あーいや、どうなんだろう
4:14 AM
そもそも クラスの場合も、暗黙のゼロ初期化initは呼ばれてるんじゃないだろうか
4:16 AM
えっと、代入文のコンパイル結果って、 左辺のメモリが未初期化(uninitialized)であればinitだけでいいんだけど、 初期化済みである場合、既存の値の破壊(参照型なら参照カウンタ減らしたり)を正しくやらないといけなくて
Avatar
複数引数funcにnamed tuple渡せなくなったから微妙かな @t.ae
Avatar
omochimetaru 7/12/2017 4:17 AM
でもSwiftって引数なしinitを持たない型も作れるよね・・・?
4:17 AM
引数なしinitな型に対して initializedなself を自動生成できない気もするし、型システムが限定されてるから無理やり作れる気もする・・・
4:20 AM
alloc済みだけどuninitedなストレージ : でたらめな数値が入ってるから破壊処理(ポインタ辿ったり)はできない / してはならない alloc済みでinitedなストレージ: その型の値として正常な状態、上書きされる場合はその前に破壊処理が必要 ( やらないとメモリリークなどが起きる ) さっきの Factory protocol で、 self = f() の左辺値の self の状態は ↑ のどっち? initedだとすると、そのinitedな値を作るための イニシャライザ は どうやってコンパイラは呼び出した?
Avatar
omochimetaru 7/12/2017 4:28 AM
おっ・・・
4:28 AM
except that copy_addr may be used even if %0 is of an address-only type. The copy_addr may be given one or both of the [take] or [initialization] attributes: [take] destroys the value at the source address in the course of the copy. [initialization] indicates that the destination address is uninitialized. Without the attribute, the destination address is treated as already initialized, and the existing value will be destroyed before the new value is stored.
4:29 AM
SIL命令copy_addr にオプションがつけられて、takeなら破壊、initializationなら初期化
4:30 AM
@norio_nomura の貼ったSILコードを抜粋すると (edited)
4:30 AM
... copy_addr [take] %6 to [initialization] %3 : $*Self, loc "<stdin>":4:14, scope 3 // id: %8 ... copy_addr %3 to [initialization] %0 : $*Self, loc "<stdin>":5:5, scope 3 // id: %10 ... (edited)
4:31 AM
%0はメソッドのレシーバ、%3はローカル変数のself、%6はf()の戻り値の格納先なので
4:32 AM
f()は完全なオブジェクトを返して、それを破壊しながらローカル変数のselfに初期化代入、つまりムーブ そのselfを、レシーバの真のselfに 初期化代入、そのあとdesstroy_addrで%3を破壊してるんで、ここはコピー
4:33 AM
結論として、allocはされてるけど、initはされてない形で全部回ってますね
4:33 AM
ちゃんとコンパイラはわかっているっぽい
Avatar
norio_nomura 7/12/2017 4:34 AM
extension Int: Factory {}Intに特化されたやつ // thunk sil shared [transparent] [reabstraction_thunk] @reabstraction thunk helper from @callee_owned () -> (@unowned Swift.Int) to @callee_owned () -> (@out Swift.Int) : $@convention(thin) (@owned @callee_owned () -> Int) -> @out Int { // %0 // user: %3 // %1 // user: %2 bb0(%0 : $*Int, %1 : $@callee_owned () -> Int): %2 = apply %1() : $@callee_owned () -> Int, scope 7 // user: %3 store %2 to %0 : $*Int, scope 7 // id: %3 %4 = tuple (), scope 7 // user: %5 return %4 : $(), scope 7 // id: %5 } // end sil function 'reabstraction thunk helper from @callee_owned () -> (@unowned Swift.Int) to @callee_owned () -> (@out Swift.Int)'
Avatar
omochimetaru 7/12/2017 4:35 AM
store %2 to %0 で普通にコピーですね
4:35 AM
まあIntはtrivialなんでそもそもinitedかどうかとかが無い
4:35 AM
無駄は無い
4:35 AM
個人的に気になるのはprotocolの汎用版のまま struct について実行されるケース。
Avatar
これの本当に微妙なところは差し替えられるselfが実はallocだけされていること、であってるかしら
-O つけると普通に無駄な alloc/dealloc 無くなっているので気にしなくて良い方向になってきた。
Avatar
おお
Avatar
omochimetaru 7/12/2017 4:37 AM
マジか
Avatar
struct Factory<T> { func `init`(_ f: () -> T) -> T { return f() } } let foo = Factory { let a = 1 let b = "2" return Foo.init(a: a, b: b) } こっちはダメだった 😢
Avatar
omochimetaru 7/12/2017 4:44 AM
文字列つかったらsilが5000行ぐらいになるな
4:46 AM
ああ printもやばい 800行ぐらいふえる
Avatar
norio_nomura 7/12/2017 4:49 AM
#linux-swiftへ少し書いたけど、swift-corelibs-foundationのprotocol Factoryを使った書き換えの範囲がかなり広がって来てます。 https://github.com/apple/swift-corelibs-foundation/pull/1095
Avatar
omochimetaru 7/12/2017 4:53 AM
-O のやつがよくわからない・・・
4:53 AM
selfを書き換える挙動が無くなっちゃってるように見える(見落としている
5:00 AM
うーむ。いろいろ試してみたけど、-Oで最適化されすぎちゃって、よくわからなかった。
Avatar
omochimetaru 7/12/2017 5:10 AM
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
5:13 AM
URLがファイルじゃなかったらData読んできて2バイトだけみて UTF16 BOM検出して、 CFStringの関数で初期化して、 最後に self.init(factory: _unsafeReferenceCast(cf, to: NSString.self)) で、 CFのオブジェクトで差し替え
5:14 AM
CFStringを _unsafeReferenceCast とやらで無理やりキャストしつつ、selfを差し替えるから
5:14 AM
Toll-Free Bridgeがここで仕込まれる
5:14 AM
よくうごくなあ・・・
5:19 AM
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
5:19 AM
そのパッチを当てる前の実装は謎だ guard let enc = enc, let cf = CFStringCreateWithBytes(kCFAllocatorDefault, bytePtr, readResult.length, CFStringConvertNSStringEncodingToEncoding(enc.pointee), true) else { throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileReadInapplicableStringEncoding.rawValue, userInfo: [ "NSDebugDescription" : "Unable to create a string using the specified encoding." ]) } var str: String? if String._conditionallyBridgeFromObjectiveC(cf._nsObject, result: &str) { self.init(str!) } else { (edited)
5:20 AM
cfのオブジェクトを作ったあと、_conditionallyBridgeFromObjectiveCで CFStringを Swift.String にキャスト?して
5:20 AM
self.init(String) に渡してる
Avatar
cf._nsObject
5:21 AM
ここがNSObjectへのキャストでは
5:21 AM
NSObjectをどうにかしてStringのポインタにぶち込んでる
Avatar
omochimetaru 7/12/2017 5:21 AM
internal init(_ string: String) { _storage = string } 最終的にどうやってToll Free Bridgeを成立させてたんだ?
5:22 AM
open class NSString : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSCoding { private let _cfinfo = _CFInfo(typeID: CFStringGetTypeID()) internal var _storage: String
5:22 AM
物理的にやってる気配がする
Avatar
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
Avatar
omochimetaru 7/12/2017 5:24 AM
open class NSString : NSObject, NSCopying, NSMutableCopying, NSSecureCoding { public static var supportsSecureCoding: Bool = true
Avatar
ということは、NSStringを作るためにNSStringからStringを抽出してNSStringをまた作って…とやっていたので
Avatar
omochimetaru 7/12/2017 5:24 AM
新しい版だとそれがなくなってる
Avatar
確かにそれならFactoryでalloc一回ぐらい多くてもどうとでもなる、というのはわかるw
Avatar
omochimetaru 7/12/2017 5:25 AM
@tarunon
} else if type(of: source) == _NSCFString.self {
この分岐みてるんだけど
5:26 AM
CFStringの中身をコピーしてSwift.String作ってる?
5:27 AM
中身コピーなくなってるならめちゃめちゃパフォーマンスが上がるよねこれ・・・
Avatar
33行目の分岐如何によってはコピーしそう
5:28 AM
String(cfString:)はコピーするのかな
Avatar
omochimetaru 7/12/2017 5:29 AM
result = String(cString: str!)
5:29 AM
cfString:じゃなくてcString:だね
Avatar
てかここはif let 使ってないのはなんでだ
Avatar
omochimetaru 7/12/2017 5:30 AM
C文字列のポインタコピーだと誰かが所有権を持たないといけないけど
5:32 AM
Swift String reference
5:32 AM
Swift.Stringの init(cString:)は中身コピーだね
5:33 AM
33行目はどっちにいっても中身コピーだと思う。
5:35 AM
initの中でselfが書き換えられる事がわかったことで
5:35 AM
toll-free-bridgeをバイナリレイアウト互換でやっていたのを
5:35 AM
本当にNSStringとしてCFStringのポインタを返すやりかたに
5:35 AM
変更できたんだとすれば
5:36 AM
めちゃめちゃ大きい成果だと思う・・・
Avatar
norio_nomura 7/12/2017 5:47 AM
NSNumber のバグフィックスPRに protocol Factory を使った甲斐があったw
Avatar
omochimetaru 7/12/2017 5:47 AM
そこがきっかけなんですか?
Avatar
norio_nomura 7/12/2017 5:47 AM
そう
Avatar
omochimetaru 7/12/2017 5:48 AM
おお・・・
Avatar
norio_nomura 7/12/2017 5:49 AM
最初書いてたPRだと上手くいかないパターンを見つけて、Factoryを使う様に書き直したのです。 https://github.com/apple/swift-corelibs-foundation/pull/1093
This replaces #1025 by further utilizing the Factory Initializer Method (SR-5255). Use CFNumberCreate() as factory initializer on NSNumber.init(value:) Change NSNumber.init(value:) to returning i...
Avatar
omochimetaru 7/12/2017 5:50 AM
なるほど
Avatar
norio_nomura 7/12/2017 5:57 AM
最終的にどうやってToll Free Bridgeを成立させてたんだ?
メモリレイアウトが同じになる様、プロパティを配置しているはずです。
Avatar
omochimetaru 7/12/2017 5:57 AM
open class NSString : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSCoding { private let _cfinfo = _CFInfo(typeID: CFStringGetTypeID()) internal var _storage: String 物理的にやってる気配がする
5:57 AM
そうみたいでした。
5:58 AM

SwiftのToll-Free Bridgeの実装を読む

Toll-Free Bridgeとは

Objective-CにはToll-Free Bridgeという仕組みがありました。 これは、C言語のライブラリであるCore...
Avatar
norio_nomura 7/12/2017 5:58 AM
NSNumberの場合、CoreFoundationでの実装を見る限り固定長ではなくなってて、Swift側のメモリレイアウトが完全には互換になってなかった。 (edited)
Avatar
omochimetaru 7/12/2017 5:58 AM
昔NSDataについては調べたけど、これがもう古くなりますね
Avatar
norio_nomura 7/12/2017 6:00 AM
それを互換にするにはFactoryを使ってCoreFoundationで初期化するのがベストという結論になったです。
Avatar
omochimetaru 7/12/2017 6:01 AM
でNSNumberの場合、CoreFoundationでの実装を見る限り固定長ではなくなってて、Swift側のメモリレイアウトが完全には互換になってなかった。
あ〜〜〜〜〜
6:01 AM
型識別子とunionみたいな事をやっていたからか
6:02 AM
NSNumberというかNSValue由来?
Avatar
norio_nomura 7/12/2017 6:05 AM
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
6:09 AM
16バイトになる場合があったけど、考慮されてなかった。 https://github.com/apple/swift-corelibs-foundation/blob/master/CoreFoundation/NumberDate.subproj/CFNumber.c#L1291
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
Avatar
omochimetaru 7/12/2017 6:09 AM
うわ、ビット指定子だ
6:10 AM
なるほど〜
6:10 AM
CFNumberの中だけでこういうバイトサイズ最適化とかやってたんですね
6:11 AM
てか kCFNumberSInt128Type って128bit signed intか・・
6:12 AM
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
Avatar
norio_nomura 7/12/2017 6:12 AM
そう、NSNumberの動きを調べると色々CoreFoundationへ丸投げされてるので、Swiftでも同様に丸投げするのが近道。
Avatar
omochimetaru 7/12/2017 6:12 AM
add128とかある。
6:13 AM
なるほどです
Avatar
norio_nomura 7/12/2017 6:14 AM
Swiftの仕様がそれを妨げていたけど、protocol Factoryの抜け道で可能になった。
6:15 AM
ここでprotocol Factoryの話をしていなかったら、起きなかったことですよ 😉
😃 1
Avatar
omochimetaru 7/12/2017 6:18 AM
たしか @rintaro さんが self 書き換え術について紹介してて、 @rintaro さん自身がそれを知ったのは Swift の stdlib のどっかで見たって話だったんで、
6:18 AM
めぐりめぐっている
Avatar
紹介されてからの、「なんだこれ、ヤベェ」→「いっちょやるか~」の動きはアグレッシブで好き
Avatar
https://github.com/apple/swift/pull/4087/files @norio_nomura この PR 引き継ぎません?今だったらマージされるかも。
What's in this pull request? I'm not sure this can be accepted or not. But this is convenient in some cases. Using that: Simplify copy constructor of NSSet and NSDictionary Eliminate getVaList fro...
6:29 AM
NSPredicateNSExpressionが無いな。
Avatar
Apple版 SDK オーバーレイの方なんです。
Avatar
norio_nomura 7/12/2017 6:33 AM
あああ、なるほど。
6:40 AM
チームが違うからphauslerさんもそのPRの存在も知らないのか。
Avatar
norio_nomura 7/12/2017 6:50 AM
swift-corelibs-foundationの方を引き合いに出すことになって、やぶ蛇になりそうな気がしなくもない… 🤔
Avatar
その可能性は大いにあるw
😭 1
Avatar
norio_nomura 7/12/2017 6:54 AM
とりあえず、マージされてなくても困っていなかったものであるなら、swift-corelibs-foundationでもう少し既成事実が出来上がるのを待ちたいw
👍 1
Avatar
政治だ…w
Avatar
omochimetaru 7/12/2017 6:54 AM
PR4087では
6:54 AM
このself書き換えって今後安定性どうなのよって
6:54 AM
話の流れになってるんですね。2016年8月に。
Avatar
既成事実化→壊せなくなった→安定性保証されたから問題ない
6:55 AM
まあそれはそれとして、
Avatar
omochimetaru 7/12/2017 6:55 AM
おもしろいな・・・w
Avatar
convenience initでself代入出来るようにしたほうがはやいんとちゃう、っていうのは思う
6:56 AM
既成事実化した後でこっちのほうが筋が良いよって話になるのが良いのかな
Avatar
norio_nomura 7/12/2017 6:56 AM
ですね
Avatar
norio_nomura 7/12/2017 7:33 AM
-O のやつがよくわからない・・・ selfを書き換える挙動が無くなっちゃってるように見える(見落としている
7:35 AM
呼び出されるときに %0 がアロケートされたメモリを差すポインタになってて、それをそのまま apply %1(%0) でクロージャへ渡してる。 // Factory.init(() -> A) -> A sil hidden @(extension in main):main.Factory.init (() -> A) -> A : $@convention(method) <Self where Self : Factory> (@owned @callee_owned () -> @out Self, @thick Self.Type) -> @out Self { // %0 // user: %4 // %1 // users: %4, %3 bb0(%0 : $*Self, %1 : $@callee_owned () -> @out Self, %2 : $@thick Self.Type): debug_value %1 : $@callee_owned () -> @out Self, let, name "f", argno 1, loc "<stdin>":3:12, scope 2 // id: %3 %4 = apply %1(%0) : $@callee_owned () -> @out Self, loc "<stdin>":4:18, scope 3 %5 = tuple (), scope 3 // user: %6 return %5 : $(), loc "<stdin>":5:5, scope 3 // id: %6 } // end sil function '(extension in main):main.Factory.init (() -> A) -> A' (edited)
Avatar
omochimetaru 7/12/2017 7:36 AM
そうなんですけど、それだとインスタンスが差し替わるパターンに対応できないですよね
7:36 AM
実際のインスタンスが何の型になってるかは、 %1のクロージャの返り値次第です
Avatar
norio_nomura 7/12/2017 7:38 AM
あいや、selfはポインタのポインタなのか。
Avatar
omochimetaru 7/12/2017 7:38 AM
あ〜
Avatar
norio_nomura 7/12/2017 7:39 AM
呼び出し側 alloc_global @main.foo : Swift.Int, loc "<stdin>":9:5, scope 1 // id: %2 %3 = global_addr @main.foo : Swift.Int : $*Int, loc "<stdin>":9:5, scope 1 // user: %11 … %11 = apply %4<Int>(%3, %10, %6) : $@convention(method) <τ_0_0 where τ_0_0 : Factory> (@owned @callee_owned () -> @out τ_0_0, @thick τ_0_0.Type) -> @out τ_0_0, loc "<stdin>":11:1, scope 1
7:41 AM
Creates a reference to the address of a global variable which has been previously initialized by alloc_global. It is undefined behavior to perform this operation on a global variable which has not been initialized.
Avatar
omochimetaru 7/12/2017 7:41 AM
直前のalloc_globalと連動しているのか
Avatar
ごめんなさい
-O つけると普通に無駄な alloc/dealloc 無くなっている
これは嘘だったぽい結論
Avatar
norio_nomura 7/12/2017 7:42 AM
呼び出し前にallocされてるのが無駄になるってことですね
7:44 AM
ただ、さっきのgistで使ったIntの例だと、-OFactory.init(_:)の呼び出し自体が無くなってる。
Avatar
omochimetaru 7/12/2017 7:44 AM
ポインタのポインタになってます?
Avatar
norio_nomura 7/12/2017 7:44 AM
a reference to the address of a global variableですね (edited)
7:47 AM
最適化でクロージャ自体が無くならない様な例にしないと…
Avatar
omochimetaru 7/12/2017 7:50 AM
ただ、さっきのgistで使ったIntの例だと、-OでFactory.init(_:)の呼び出し自体が無くなってる。
ああ、ですね。
Avatar
norio_nomura 7/12/2017 7:52 AM
そう、なので -O だとジェネリックな実装が呼ばれないので、無駄なalloc/deallocって無いような気がする。
Avatar
omochimetaru 7/12/2017 7:53 AM
はい、ただ、 ライブラリ側で Factory.init(_:) を提供していて 別のリンク単位からそれを使う場合は
7:53 AM
その最適化はできないので
7:53 AM
その場合にどうなるかですね・・・
Avatar
Factory.init(_:)extension NSObject: Factory を提供するだけのライブラリ作って、Kotlinパワーを手に入れるぞ!!とか考えてた
Avatar
norio_nomura 7/12/2017 7:54 AM
swift-corelibs-foundationではFactoryinternalになってますね。
Avatar
omochimetaru 7/12/2017 7:54 AM
swift-corelibsで CF差し替えとかで使ってる限りはその部分はこのようにインライン化されてそうですね。
Avatar
norio_nomura 7/12/2017 7:55 AM
あいや、swift-corelibs-foundationの場合は無駄になってますね。 (edited)
Avatar
omochimetaru 7/12/2017 7:55 AM
あら?
Avatar
Factory.init を使う public convenience init の呼び出し前に alloc されちゃうので
7:56 AM
少なくとも現状は無理ぽい。
Avatar
一番外側でFactory.initなら無駄がない?
Avatar
norio_nomura 7/12/2017 7:59 AM
全部Swiftで完結しててFactoryinternalなら無駄は 無くなりそう。 無くならない。 (edited)
Avatar
omochimetaru 7/12/2017 7:59 AM
ふむふむ
Avatar
norio_nomura 7/12/2017 8:01 AM
public initの中でFactory.init(_:)を使っている場合、Standard Libraryのメソッドならインライン化されて無駄にならないのかな?
8:01 AM
Standard Libraryは特別にインライン化される仕組みでしたよね、確か。
Avatar
https://gist.github.com/rintaro/b56487baafcfde7767c21193c540ffce これでも alloc/dealloc 走っているので、 convenience init 使ってる限りだめっぽいです。
Avatar
norio_nomura 7/12/2017 8:24 AM
なるほど // makeBase(a : Int) -> Base sil @main.makeBase (a : Swift.Int) -> main.Base : $@convention(thin) (Int) -> @owned Base { bb0(%0 : $Int): %1 = alloc_ref $Base, scope 6 // users: %6, %7 %2 = alloc_ref $Base, scope 16 // users: %8, %5, %4, %3 debug_value %2 : $Base, let, name "self", loc "<stdin>":10:15, scope 23 // id: %3 debug_value %2 : $Base, let, name "s", argno 1, loc "<stdin>":4:10, scope 29 // id: %4 debug_value %2 : $Base, let, name "s", argno 1, loc "<stdin>":4:10, scope 29 // id: %5 %6 = value_metatype $@thick Base.Type, %1 : $Base, loc "<stdin>":15:10, scope 32 // user: %7 dealloc_partial_ref %1 : $Base, %6 : $@thick Base.Type, loc "<stdin>":15:10, scope 32 // id: %7 return %2 : $Base, loc "<stdin>":20:3, scope 4 // id: %8 } // end sil function 'main.makeBase (a : Swift.Int) -> main.Base'
Avatar
norio_nomura 7/12/2017 8:35 AM
scope 6Base.init()scope 16Base.init(_:)で、それぞれで alloc_ref が動いてる。
Avatar
norio_nomura 7/12/2017 8:59 AM
NSNumberkCFBooleanFalseに差し替え、当然__ObjC.NSNumberallocは無くならない。 https://gist.github.com/norio-nomura/1632926c9163ea03e4d9ff701b1fac51
Avatar
omochimetaru 7/13/2017 3:34 AM
Ruby の 1..2 は Swift の 1...2 で Ruby の 1...2 は Swift の 1..<2... の意味が逆・・・
Avatar
最初出た頃思いましたw
3:36 AM
いや、最初は揃ってたんだっけ...うる覚え
Avatar
omochimetaru 7/13/2017 3:37 AM
今のSwiftの状態は覚えやすくて良い。 . が 数直線の端にうった ● の事だと思うと 1...2 の左の点と右の点は 含むよって意味にとると筋が通る
Avatar
なら半開区間は..。か・・・
Avatar
omochimetaru 7/13/2017 3:38 AM
白丸の代わりが < で。
3:39 AM
将来的に左を含まないやつが出るときには 1<..21<.<2 になってくれると嬉しい (edited)
Avatar
なるほど、たしかに右辺左辺両方表現できて良さそう
Avatar
1<..2欲しい…
Avatar
omochimetaru 7/13/2017 3:42 AM
どんなときにほしいと思ったんですか?
Avatar
switch 文の範囲指定の時ですね
3:43 AM
今ですと、例えば1より大きい時の範囲を描く場合は case let x where x > 1 を書くか、case 1 ... .max の前に case 0 ... 1 を書かないとダメなので
Avatar
~=でも
Avatar
omochimetaru 7/13/2017 3:47 AM
なるほど。たしかに不等式でswitchしたい時に 大なり が取りたくなるとそうなのか。
Avatar
最終的には case .min ..< 0: case 0: case 0 <.. .max だけで網羅性確認済みにして欲しい
Avatar
omochimetaru 7/13/2017 3:48 AM
たしかにif文で if (x < 0) { } else {} って書くより switch でそう書けて、網羅検査されたほうが、 両方のパターンが明記されて嬉しいな
3:48 AM
if で網羅しようとすると最後の else に条件が書けないか、条件を書く + 空のelseになるから switch - case にしたくなる時がある
Avatar
ですよね
Avatar
omochimetaru 7/13/2017 3:49 AM
めっちゃほしくなってきた
Avatar
何よりif else文よりswitch case文の方がスマートに見える()
Avatar
if (a) { } else if(b) {} else {} だとb時点でaでないってことを頭に入れながらelseも考えないといけないから実は読みづらかったり
Avatar
omochimetaru 7/13/2017 3:51 AM
そうそう
Avatar
でもそれswitch文でも同じですね、case b: の時点では case a: でないということ
3:52 AM
さっきの例ですとまさに case 0 ... .max で書いた時は仮にもしその前に case 0: があったら0の時に case 0 ... .max に入ることはないということ
Avatar
確かに
最終的には case .min ..< 0: case 0: case 0 <.. .max だけで網羅性確認済み
ここで網羅性まで抑えてくれてdefault書かなくて良くなったら最高ではあります
Avatar
作るかw
3:59 AM
switch case文で使える ~= だけに対応するやつなら多分作れるんじゃないかと
Avatar
話の流れと関係ないけど let a = [1,2,3] a[...] // -> [1,2,3] これの実現をしているコードがすごい
Avatar
omochimetaru 7/13/2017 4:05 AM
a[...] こんなのありましたっけ
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 7/13/2017 4:06 AM
+// FIXME: replace this with a computed var named `...` when the language makes +// that possible. +public enum UnboundedRange_ { + public static postfix func ... (_: UnboundedRange_) -> () { + fatalError("uncallable") + } +} +public typealias UnboundedRange = (UnboundedRange_)->() + public subscript(x: UnboundedRange) -> SubSequence { + get { + return self[startIndex...] + } + set { + self[startIndex...] = newValue + } + }
4:07 AM
あっ、これ、そういうことか?
4:08 AM
... は 演算子で、 形式的に UnmoundedRange_ を引数1個取って消化する関数で
4:08 AM
subscript は、 UnboundedRange_ を消化する関数を受け取るオーバーロードなのか。
4:09 AM
お、このテクニックで、好きな演算子を、演算子単体で存在する型として取り回すことができるな。
Avatar
ダメだ、< で始まる演算子が作れないorz
Avatar
なるほど...dummyの演算子を置いてってことなんですね
Avatar
omochimetaru 7/13/2017 4:10 AM
しかもそこで 0 case enum を使って 実際にその値が作れないようにしていますね
Avatar
作れませんか?
Avatar
. を含む operator は . が最初になければいけない言語仕様。
👍 1
Avatar
omochimetaru 7/13/2017 4:10 AM
魔力高い
Avatar
読めない英語のメッセージが出た
Avatar
.<..<< 作るか
Avatar
omochimetaru 7/13/2017 4:10 AM
@tarunon が好きそうだからリプライ送っておこう
Avatar
<===とかは作れる
Avatar
なんにゃ
Avatar
Swift定義済みのPrecedence一覧ってどっかないですかね?
Avatar
omochimetaru 7/13/2017 4:13 AM
@tarunon ちょっと↑にある array[...] っていうコードの実現方法がトリッキー。 ... は省略じゃなくて どっと3つのコード (edited)
Avatar
なんだこれw
Avatar
確認するときは import Swift 打って Cmd + クリックしちゃいます。 > Precedence一覧
Avatar
おおお流石! @rintaro
Avatar
. を含む operator は . が最初になければいけない言語仕様。 これがボディーブローのように効いてるような気がする
4:17 AM
上界と下界が閉じてる開いてるの違いを表現するのに、1つめと3つめの.を変化させるのが絶対に理解しやすいと思うんだけどな
👍 1
4:19 AM
..., ..<, <.. <.<で4通り、意味もパット見で即理解できる
Avatar
omochimetaru 7/13/2017 4:19 AM
4つめは <..< のほうがいいきがしてきた
Avatar
意味さえわかればそれでおk
4:20 AM
... は 演算子で、 形式的に UnmoundedRange_ を引数1個取って消化する関数で subscript は、 UnboundedRange_ を消化する関数を受け取るオーバーロードなのか。 お、このテクニックで、好きな演算子を、演算子単体で存在する型として取り回すことができるな。
4:20 AM
これがテンション高い
Avatar
omochimetaru 7/13/2017 4:21 AM
↑それを見てほしかった
Avatar
pythonのarray[:]みたいなのができそう
Avatar
関数を受け取る関数を作ってそこにオペレーターをぶち込めるの、脳汁湧きますね
4:21 AM
世界が広がった
Avatar
omochimetaru 7/13/2017 4:22 AM
0 case enum をつかってそれの直接利用も封じてある
Avatar
ため息が出る
Avatar
Xcode9 で _ 打つと UnboundedRange_ が補完されるのがうざいw (edited)
Avatar
なるほどなるほど~~~
😋 1
Avatar
omochimetaru 7/13/2017 4:23 AM
@rintaro 本当だ
Avatar
myObject.hello(+, x) と myObject.hello(-, x)で別の関数を呼ぶとか出来ますね
4:24 AM
しかしこれ、中二病心を擽るけど実用したら他の人死んじゃうのでは
Avatar
omochimetaru 7/13/2017 4:25 AM
それはそう
Avatar
あーー
4:25 AM
結構便利な利用シーンは思いついた
4:25 AM
あとで試してみよう
4:26 AM
これoperatorならではのハックなんですかね?普通の関数名でやりたい
4:26 AM
dataSource(reload, ....) と dataSource(animated, ....) を分離出来るのは思いついていて
Avatar
omochimetaru 7/13/2017 4:26 AM
普通の関数だと () つけないといかんのでは? グローバル変数使えばいけるかな
Avatar
グローバルに関数を置くのは忍びないな
4:27 AM
まあ引数が存在しない0 enumなら許せるか
Avatar
よし最低限の実装書いたった
Avatar
omochimetaru 7/13/2017 4:31 AM
.<< にしたんですね .<.. とかはどうでしょう?
Avatar
.<<.<. にしてました😇
Avatar
omochimetaru 7/13/2017 4:32 AM
なるほど
Avatar
やっぱり <..<.< 使いたいんですよね😇
4:34 AM
さてこれEltasoの中に入れとくべきか別フレームワークにすべきか悩む
4:35 AM
(まあ使う人そんなにいないでしょうからEltasoに入れるのも悪くない気がしないでもないがなんかEltasoがだんだん何でも屋になってきて微妙
Avatar
omochimetaru 7/13/2017 4:36 AM
Eltaso - This is a framework that contains some convenient methods and extensions for myself
4:36 AM
いろいろありますねえ
Avatar
色々ありすぎて自分のプロジェクトに大体これインポートしてるので依存性がやばい気がする、特に引き継ぐ人にとって😇
Avatar
全部入りは何かとしんどそう
Avatar
omochimetaru 7/13/2017 4:39 AM
こういうの作りたくなる気持ちはめっちゃわかる
Avatar
SwiftCoreLibとFoundation、それからUIKitぐらいは区切ってもいいと思いました
4:40 AM
拡張元のモジュールごと、ですね
Avatar
omochimetaru 7/13/2017 4:40 AM
Matrix<T> とかは?
Avatar
FoundationExはSwiftCoreLibExをimportするんじゃないかな
Avatar
Eltaso最初作った時はあんまり深く考えてなかったんですよね、最初の頃はただ単にハッカソンやっててこういうの欲しいなって思ったやつをとりあえず入れといてみただけのフレームワークですけど、やがて仕事にもこれ使い始めて気づいたらやばいことにw
Avatar
omochimetaru 7/13/2017 4:41 AM
ww
Avatar
Matrix<T>はさすがにそろそろ出してもいいじゃないかと思ったり
Avatar
Matrixはサイズを型に持たせて安全にしたくある
Avatar
https://github.com/el-hoshino/Eltaso/blob/master/Eltaso/Eltaso/Matrix.swift#L148-L166 このパターン楽なんですけどtranspose()のほうが実装を持ってtransposedがそれを使うほうが速度的にはいいよなといつも思う (edited)
Eltaso - This is a framework that contains some convenient methods and extensions for myself
Avatar
速度的にはそっちの方が早いですね
4:46 AM
ただなるべく直接自分自身をいじらないようにしてますので、いじる時は必ずバックアップとってバックアップの方をいじって自分自身をバックアップにするというスタンスを取ってますので()
4:47 AM
特にMatrixみたいなやつだといじってる途中で落ちたりしたらめっちゃ怖い気がw
Avatar
swift書いてるとだいたいletで取り回すんで自分自身を書き換えるほうが主になると変な気分になりますよね (edited)
Avatar
ですね
Avatar
ご飯食べてたら乗り遅れた・・・
5:12 AM
<..<.< 、前にここで話してたときに作ろうとしてコンパイラに阻まれて諦めた・・・
Avatar
やはりすでに屍、じゃなかったパイオニアが
Avatar
でもそれも実現したら Swift4 の Range 系の型が爆発してヤバそう・・・
5:14 AM
1... とかもできたし、 Countable もあるし
Avatar
<..<.< はさすがに起点がないから Countable は作れないと思いますね
5:15 AM
なので多分 Strideable には作れないと思います
Avatar
整数なら数えられませんか?
5:16 AM
one sidedなら無理ですが
Avatar
今の Countable って条件は要素が Strideable だっけ?
Avatar
let a: CountableRange<Int> = 1..<10 // OK (edited)
Avatar
public struct CountableRange<Bound> : RandomAccessCollection where Bound : Comparable, Bound : _Strideable, Bound.Stride : SignedInteger { (edited)
Avatar
public struct CountableRange<Bound> : RandomAccessCollection where Bound : Comparable, Bound : _Strideable, Bound.Stride : SignedInteger ふむふむ
Avatar
_Strideable は実質的に Strideable です。
Avatar
Striderableに始点が必要なのか Striderableで左開区間なら左辺値の次が取れるはずなんでCountableにできそうな (edited)
Avatar
左辺値の次の値で取るって仕様って実際どうですかね?それかけるなら次の値わかる気がしないでもないような…
5:20 AM
あるとすれば数字が一致させられることに意味があるなのかな?
Avatar
(0, 10].count == [0, 10].count - 1
Avatar
@lovee 色々ありすぎて自分のプロジェクトに大体これインポートしてるので依存性がやばい気がする、特に引き継ぐ人にとって😇 @tarunon 全部入りは何かとしんどそう @omochimetaru こういうの作りたくなる気持ちはめっちゃわかる
僕もこういうのほしくなるんですが、細かく分割して、全部 dependencies に突っ込んだライブラリ一個作って、自分が使うときはそれを使えば全部引っ張ってこれるんじゃないかと考えてます。ついでに、全部入りの方で typealias 作りまくったら、全部入りの一つ import したら全部使えそう。試してないんで落とし穴があるかもですが。
Avatar
マイクロフレームワークアーキテクチャですね
Avatar
ただ、困るのは分割した A と B の両方を組み合わせた機能をどうするかなんですよね。
Avatar
omochimetaru 7/13/2017 5:24 AM
組み合わせた機能を提供する C を作るか、 A -> B か B <- A のどちらかで依存を規定するか
Avatar
でも問題は結局のところ、自分のプロジェクトを引き継ぐ人が依存されてるライブラリーをわかってないと辛いってところですね
Avatar
内部的に使うとかなら片方に依存でいいんですが、 AとAのextension的なBがあったときが悩ましい
Avatar
omochimetaru 7/13/2017 5:25 AM
まあ引き継ぐ時と自分が作る時、どっちに負担を寄せるかっていうのはどっちかを選ぶしか無いから
Avatar
それはBにimport Aですかね?
Avatar
omochimetaru 7/13/2017 5:26 AM
自分が楽に作れる方に寄せといて、引き継ぐ時に必要ならライブラリを分割するとか剥がすとか教えるとかしたらいいんでは
5:26 AM
それはもう本来的に回避できない引き継ぎコストなんだと思う
Avatar
組み合わせた機能を提供する C を作るか、 A -> B か B <- A のどちらかで依存を規定するか
A と B はシンプルに保ちたいから依存はしたくなくて、でも C を作り出すと組合せ爆発する。
Avatar
omochimetaru 7/13/2017 5:27 AM
ある程度作って丸投げ納品するみたいなあとで引き継ぐ予定がはっきり決まってるときはおいといて、だいたいはあとのことは不確定だから今のことを有線した方がいい
Avatar
例えば、 PromiseResult のライブラリがあって
Avatar
演算子はなんか行儀悪いって思ってしまう、そんなこと言ったらRxなんかどうなるだって話ですけど
Avatar
組み合わせてエラー処理を含んだ Promsie<Result<T>> についての extension を作って
5:27 AM
一方で Runes の演算子使ったとき用の拡張を作りたくて、 Promise+Runes, Result+Runes ができて
5:28 AM
(演算子は衝突するので元のライブラリから分離しておきたい)
Avatar
import funcで頑張る案
Avatar
じゃあ Promise+Result+Runes もほしくて、とか。
Avatar
omochimetaru 7/13/2017 5:28 AM
ライブラリ単位で依存グラフ作っていくとややこしくなるので
5:29 AM
本当は 「このライブラリを一緒に使っているなら有効化される」 っていう仕組みがあったらいいのかな?
Avatar
うん。そういうのがほしい。
Avatar
omochimetaru 7/13/2017 5:29 AM
依存じゃなくて連携機能。
Avatar
弱依存みたいな。
5:29 AM
あったら使えるけどなかったら消える。
Avatar
omochimetaru 7/13/2017 5:29 AM
C/C++だとmakefileでそこらへんを検査してマクロスイッチでコントロールしたりできますね
5:29 AM
なんなら依存先ライブラリを切り替えたりもする
5:30 AM
Swiftにも #if があるから Package.swift での制御とか組み合わせたらそういうことをやる余地あるかな (edited)
Avatar
共通のプロトコルを同じ分野のライブラリで協定結んじゃった方がって気も... さすがに用途一緒だからってスイッチできる仕組みを考え出すと大変そう
Avatar
C -> A, B のときに、 A のビルド時の #if で C が B にも依存していることを検知して切り替えるのは難しそう。
Avatar
ライブラリ単位で依存グラフ作っていくとややこしくなるので
本当は 「このライブラリを一緒に使っているなら有効化される」 っていう仕組みがあったらいいのかな? 欲しい
Avatar
omochimetaru 7/13/2017 5:32 AM
#if is_spm_include("B") (edited)
Avatar
共通のプロトコルを同じ分野のライブラリで協定結んじゃった方がって気も...
うーん、でも Result は antitypical/Result を使いたいとかもありますし、Runesも代わりのOperadics があるし、自由な組み合わせで使えるようにしたいんですよねぇ。
(edited)
5:35 AM
で、これを抽象化した ResultType プロトコル作って、使う側で extension Result: ResultType すれば OK にしようとしたら、 Higher-kinded type がないのでアウト😇
Avatar
単純にライブラリ提供側が実装大変だなーとは思ったんですよね、絶対便利だからあった方がいいと思う自分もいつつ 同じ用途だと言ってA1にはこの機能あるけど、A2にはない、そしてライブラリ提供のために足りないA2を自前で補填しなきゃ...的なことを考えてました
5:38 AM
使ってもらうことを考えたらそれぐらいの苦労は問題ないかもですが
Avatar
omochimetaru 7/13/2017 5:38 AM
大変でもそれがやりたいときがあるっていう前提じゃないですかね
Avatar
そうですねー。 A と B1 を組み合わせたら便利だけど、他との依存関係の問題で B2 を使わざるを得ないときに、 A と B2 でも使えるよ、とかですね。 (edited)
Avatar
大変でもそれがやりたいときがあるっていう前提じゃないですかね
確かに、それができるってことが大きいとは思います
5:40 AM
(ライブラリ作ってて非同期ライブラリの選定にいつも悩むので切実に欲しいです)
👍 1
Avatar
↑の UnboundedRange がほしいのって、 subscript(_ f: (Element, Element) -> ClosedRange<Element>) -> SubSequence だと ... 以外が入れられるから?
Avatar
omochimetaru 7/13/2017 5:57 AM
その定義では ... が入れられなくないですか?
Avatar
let a: (Int, Int) -> ClosedRange<Int> = (...) // OK (edited)
6:00 AM
func foo<T: Comparable>(start: T, end: T, _ f: (T, T) -> ClosedRange<T>) -> ClosedRange<T> { return f(start, end) } foo(start: 1, end: 10, ...) // OK
Avatar
やるなら Element じゃなくて Index のほうが良いと思いますが、 ClosedRange 型を使いたくなかったからだと予想。
Avatar
omochimetaru 7/13/2017 6:04 AM
やっと言ってることがわかった ... 演算子自体の型をうけとけば ... が渡せるってことか。
Avatar
extension Collection { subscript(_: (Index, Index) -> ClosedRange<Index>) -> Int { return 1 } } let res: Int = [1,2,3][...] で通るので、出来なくはない。 (edited)
Avatar
extension Array { public subscript(_ f: (Int, Int) -> ClosedRange<Int>) -> ArraySlice<Element> { return self[startIndex..<endIndex] } }
6:04 AM
Swift 3.1 でできた。 (edited)
6:04 AM
let ns = [2, 3, 5] ns[...] // [2, 3, 5]
Avatar
omochimetaru 7/13/2017 6:05 AM
それだと型が一致してるクロージャでも呼べちゃうしシグネチャ見てなんだこりゃってなりそう
Avatar
<.. とか <.< とか作ろうとしたときに↑もしようとしてた。
Avatar
omochimetaru 7/13/2017 6:05 AM
UnboundedRangeって言葉が出て来るのと、 ... 演算子である事が必須になるので、そっちのほうが望ましいと思う
Avatar
ClosedRange 型を使いたくなかったからだと予想。
これは Closed の部分じゃなくて、意味の異なるものを使いたくなかったってことですよね?
🙆 1
6:08 AM
なんで UnboundedRange...infix じゃなくて postfix なんだろう?
6:09 AM
フリーで存在する後置演算子ってあまり見かけないから変な感じがする。
Avatar
1...
6:09 AM
こいつでは
Avatar
omochimetaru 7/13/2017 6:09 AM
CountablePartialRangeFrom<Int>(lowerBound: 1)
6:10 AM
ほんとだ。
Avatar
オーバーロードにぶち込む幽霊型のためなので、1引数だけで良くって、1引数だとinfixはないから (edited)
6:11 AM
大きな理由は特に無い気がする
Avatar
@tarunon [...] のためだけに使う(コールしない)ので、 infix でも postfix でも同じじゃないですか?
6:11 AM
ああ、入れ違った
6:12 AM
最小限にとどめたら 1 引数になったってことなのかな。
6:14 AM
numpy みたいに、 array[:, 2, 3, :, 5] のように書けるようにするには、 ... が nominal でないのが辛いなぁ。
6:14 AM
Union があれば解決するんだけど・・・。
Avatar
ゲッそんなの出来たのかw
6:17 AM
随分昔にちょろっと触っただけなので全容を把握してない > python
Avatar
extension Tensor { subscript(indices: Int|Range<Int>|ClosedRange<Int>|PartialRangeUpTo<Int>|PartialRangeThrough<Int>|PartialRangeFrom<Int>|UnboundedRange...) -> Tensor
6:17 AM
こうしたい・・・
6:18 AM
Countable も。
6:18 AM
..<10 もできるようになるのか。 Swift 4
6:19 AM
UnboundedRange 以外は nominal だから
Avatar
numpyの場合array[..., 1]...はそこまでの次元全てを示すからまた意味がずれる
Avatar
extension Int: Indexing {} extension Range: Indexing {} ... とかして、 extension Tensor { subscript(indices: Indexing...) -> Tensor } でいいけど、 UnboundedRange だけはどうしようもなさそう・・・。
6:21 AM
Swift で tensor[..., 2, 3, ..., 5] やりたい・・・。
Avatar
...の型にプロトコルつけられないからか。
Avatar
はい。
6:22 AM
tensor[1..., 2, 3, ..<4, 5] まではできる。
Avatar
特別な型と、その定数を用意するのが良い気がしますねぇ
6:23 AM
np.newaxisみたいに
Avatar
@t.ae それって ... 使えなくない?
Avatar
UnboundedRange <- こいつをGenericsにしてIntの場合にoperator生やすとかで誤魔化せませんかね
Avatar
@koher なので記号をどうするかが問題ですね numpyに合わせて:使えたら良かったんですけどもちろん使えない
Avatar
オレオレで作れば行けるのでは、と思ったけど
Avatar
... を演算子としてしか使えない以上どうにもならなさそう・・・
Avatar
unicode使えるんだからなんか適当なのを使えば良い気もする 入力は置いといて
Avatar
@t.ae 記号を当てるのはもちろんできるけど、それだと array[...] とかとの一貫性がなくなっちゃう・・・ (edited)
Avatar
ああ、そういうことか
6:27 AM
union欲しいの意味がわかった
Avatar
有限個なら書き下せるんだけど、パターンが無限なので書き下せない・・・ (edited)
Avatar
gybで10個ぐらいの組み合わせを生成すれば良いのでは
Avatar
ですね。
Avatar
どうせ2, ..., ..., 5みたいなのは弾かないといけないから厳密にはunionもダメ出し
Avatar
10 はちょっとやばい。 2 ^ 10 = 1024 にw
Avatar
tensor[2, ..., ..., 5] はできますよ。
Avatar
Okなんすか…
Avatar
tensorswiftに入れてましたっけ? 僕が別で書いたのはあります https://github.com/t-ae/ndarray/blob/master/Sources/Indexing.swift
ndarray - Float NDArray library for Swift, accelerated with Accelerate Framework
Avatar
@t.ae そもそもまだ TensorSlice の PR を取り込んでない気がする。
Avatar
たしかに
Avatar
@tarunon import numpy as np a = np.array([[[[1, 1], [2, 2]], [[3, 3], [4, 4]]], [[[5, 5], [6, 6]], [[7, 7], [8, 8]]]]) a.shape # (2, 2, 2, 2) b = a[0, :, :, 0] b.shape # (2, 2) c = a[0:1, :, :, 0:1] c.shape # (1, 2, 2, 1) (edited)
6:37 AM
N 次元超立方体を考えて、 : の次元は残して、インデックス指定してる次元での断面を求めてるイメージ (edited)
6:38 AM
>>> print(b) [[1 2] [3 4]] >>> print(c) [[[[1] [2]] [[3] [4]]]]
Avatar
ああなるほど、根本から誤解していた
Avatar
なるほど、普通の list だと思ってたってことですね。
6:49 AM
そっちは >>> a = np.array([2, 3, 5, 7]) >>> a[0, 2, 3] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: too many indices for array はできませんが >>> a[[0, 2, 3]] array([2, 5, 7]) はできます。 (edited)
6:49 AM
↓はできないです。 >>> a[[0, 2:4]] File "<stdin>", line 1 a[[0, 2:4]] ^ SyntaxError: invalid syntax
Avatar
深さ5の32個オーバーロードで現実的には足りそう
Avatar
↓はできるかと思ったらできませんでした・・・。 >>> a[[0, range(2, 4)]] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: too many indices for array
Avatar
深さ5の32個
One sided rangeとか入ってくると増えますよ
Avatar
Python の i:j[] の中でだけ有効な記法なので、 [[0, 2:4]] とかはそもそもあり得ないんですが、 [[0, range(2, 4)]] もだめでした・・・。
6:52 AM
@t.ae ... 以外はプロコトルでまとめるので大丈夫。
Avatar
なるほど。
Avatar
... とそれ以外の 2 通りの 5 乗。
Avatar
だめだぁ、 ... と リテラルがどうしてもつながらない。
6:53 AM
enum MyIndex { case value(Int) case range(Range<Int>) case closedRange(ClosedRange<Int>) case partialRangeUpTo(PartialRangeUpTo<Int>) case partialRangeThrough(PartialRangeThrough<Int>) case unbound } prefix func + (x: Int) -> (MyIndex.Type) -> MyIndex { return { _ in .value(x) } } func ..< (x: Int, y: Int) -> (MyIndex.Type) -> MyIndex { return { _ in .range(x..<y) } } func ... (x: Int, y: Int) -> (MyIndex.Type) -> MyIndex { return { _ in .closedRange(x...y) } } prefix func ..< (x: Int) -> (MyIndex.Type) -> MyIndex { return { _ in .partialRangeUpTo(..<x) } } prefix func ... (x: Int) -> (MyIndex.Type) -> MyIndex { return { _ in .partialRangeThrough(...x) } } postfix func ... (_: MyIndex.Type) -> MyIndex { return .unbound } func foo(_ indices: (MyIndex.Type) -> MyIndex...) { print(indices.map { $0(MyIndex.self) }) } foo(..., 0..<12, +12)
Avatar
+ExpressibleByIntegerLiteral にできそう。
Avatar
リテラルがつながらないってどういうことです?
Avatar
(MyIndex.Type) -> MyIndex... のために必要なので、 ExpressibleByIntegerLiteral にはできないのです。 (edited)
6:57 AM
「リテラルとRangeファミリー」もしくは「Rangeファミリーと ...」を受けるものは作れるけど、「リテラルとRangeファミリーと...」を全部受けるのは出来ないって言う意味です。
Avatar
やっとわかってきた・・・
7:00 AM
関数型に寄せてるんですね。おもしろい・・・。
Avatar
autoclosureにできたりしないかな
Avatar
@autoclosure だと強制になっちゃうから
Avatar
可変長の個々だから無理か・・・
Avatar
@autoclosureable みたいなのがあればいいのかも・・・
7:04 AM
まず↓ができなかった 1> func sum(_ fs: (@autoclosure () -> Int)...) -> Int { 2. return fs.reduce(0) { $0 + $1() } 3. } error: repl.swift:1:18: error: @autoclosure may not be used on variadic parameters func sum(_ fs: (@autoclosure () -> Int)...) -> Int { ^
Avatar
SE-0157: Support recursive constraints on associated types https://github.com/apple/swift/pull/10940
We don't know if they work in general, but specific cases of recursive protocol constraints are working, and enabling them doesn't break anything.
Avatar
^ Standard Libraryの変更はまだ含んでいなくて、recursive protocol constraints出来る様にするPRだった。
Avatar
protocol Sequence { associatedtype Filtered: Sequence associatedtype SubSequence: Sequence } こうなるのかな
Avatar
Mapped ができるのはいつのことやら・・・
Avatar
高階型が出来たとして、Sequenceの上位にMonadとかFunctorとか整備されるのか微妙に気になるw
Avatar
今の感じだとされなさそうですね。 Core Team はそういう方向に進むのにネガティブっぽいです。
5:52 AM
ただ、 map の結果を型によって lazy にしたいというニーズはありそう。 (edited)
Avatar
今Lazyのmapってoverloadでしたっけ?
Avatar
今どうなってるかわからないですが、 Filtered は確かそんな理由で導入されてましたよね?
Avatar
/// A sequence containing the same elements as this sequence, /// but on which some operations, such as `map` and `filter`, are /// implemented lazily. /// /// - SeeAlso: `LazySequenceProtocol`, `LazySequence` public var lazy: LazySequence<LazySequence<Base>> { get } /// Returns a `LazyMapSequence` over this `Sequence`. The elements of /// the result are computed lazily, each time they are read, by /// calling `transform` function on a base element. public func map<U>(_ transform: @escaping (Base.Iterator.Element) -> U) -> LazyMapSequence<Base, U>
5:54 AM
overloadですね
Avatar
↑見て思ったんですが、 filter@escaping になるから型が変わりそうな気が
Avatar
あーそっか
5:55 AM
そもそも引数のクロージャが @escaping になるかどうかという違いがあるから
Avatar
Sequencefilter@escaping で、 Array とかはそれを @nonescaping として上書きするんでしょうか?
Avatar
Sequenceの範疇にLazySequence入れるのがそもそも悪手な気もする
Avatar
@escaping (T) -> UT -> U のサブタイプ(?)だから、一応まとめられそう?
5:59 AM
引数のオーバーライドは反変だからスーパータイプで引数が @escaping (T) -> U だったのを (T) -> U でオーバーライドできるはず。
Avatar
throws rethrowsってLazyだとどうするべきなんですかね
Avatar
あー
6:01 AM
rethrows はできないですね。
Avatar
将来的にasync reasyncも入れるとして
6:01 AM
まあそういうの含めて
Avatar
async / await がないと。
Avatar
SequenceとLazySequenceは分けて考えたほうが良さそうで
6:02 AM
Sequence側にflatMap経由のLazySequenceへの変換と、LazySequenceにSequenceへの変換があれば
6:02 AM
すっきりすると思うんですよね
Avatar
protocol Sequence { associatedtype Filtered func filter( _ isIncluded: (Iterator.Element) throws -> Bool ) rethrows -> Filtered } extension RangeReplaceableCollection { func filter(_ isIncluded: (Iterator.Element) throws -> Bool) rethrows -> Self { var result = Self() for element in self { if try isIncluded(element) { result.append(element) } } return result } }
6:04 AM
Lazy じゃなかった?
6:04 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
RangeReplaceableCollectionは別にLazyではないのでは
Avatar
Lazy のためにほしかったと勘違いしてました。
Avatar
やっぱりどう考えてもLazyをFilteredとかの範囲だけで解決するのは無理で
6:05 AM
SequenceとLazySequenceを分離したほうが最終的に平和な気がする…
6:06 AM
というかですね
6:06 AM
@escaping (T) -> U は T -> U のサブタイプ(?)だから、一応まとめられそう? 引数のオーバーライドは反変だからスーパータイプで引数が @escaping (T) -> U だったのを (T) -> U でオーバーライドできるはず。
6:06 AM
これから導かれる結論は
6:06 AM
protocol Sequence: LazySequence {
6:06 AM
なわけで。
Avatar
そうですね。
6:07 AM
mapArray 返すけど filterSelf 返すんですね・・・。 https://developer.apple.com/documentation/swift/set/1688238-filter
6:10 AM
Setmap に Beta ってついてる・・・。なぜ??
6:10 AM
Avatar
protocol Sequence: LazySequence は割りと無理があった
6:18 AM
Set.mapがBetaなのは将来的にSetにしたいってことでは?という妄想
Avatar
Xcode 9.0+ になってるけど、昔から使えましたよね?? https://developer.apple.com/documentation/swift/set/2905183-map
Avatar
Setが生まれたときから生えてると思いますよ
6:21 AM
↑の二つ何が違うんだろう???
Avatar
Set: Collectionなので、
6:26 AM
Collectionのデフォルト実装のmapとSetのmapの実装の両方が見えてるのかな
Avatar
シグネチャが全く同じでも上書きじゃなくて共存するんですっけ??ドキュメント生成ツールの都合上?
Avatar
後者だと思います、witness-tableに登録されるしどうやってもSetでCollection.mapは呼べないと思う
🙂 1
6:52 AM
Set.mapとCollection.mapのDocComment見るとだいたい納得できそう
6:52 AM
多分2つあるmapの差分と同じ差分があると思います。
Avatar
それが確認できたらほぼ確実ですね。
Avatar
二つ の違いはわかりませんが、 Beta なのは Self.Iterator.ElementSelf.Element になったからだと思います。シグネチャ変わってしまったので。
Avatar
なるほど。
9:23 AM
確かに Array も Beta になってました。 https://developer.apple.com/documentation/swift/array/2907114-map
Avatar
enumのassociatedvalueにNever入れたこと無いから意識してなかったけど、Never入ってるcaseは無視してもコンパイル通るようになって欲しいかなとか思った
12:25 PM
enum Enum2<T0, T1> { case case0(T0) case case1(T1) } func just<T>(_ x: T) -> T { return x } func just<T>(_ x: Never) -> T { fatalError() } func foo(x: Enum2<Int, Never>) -> Int { switch x { case .case0(let x): return just(x) case .case1(let x): return just(x) } }
12:27 PM
NeverがBottomなら気にしなくても済むのかな
Avatar
KotlinのNothingはBottomなんでしたっけ、これは通ってそう? fun alwaysFail(): Nothing { throw RuntimeException() } fun <T> nothingCheck(nothing: Nothing): T { return alwaysFail() } (edited)
Avatar
Neverは本来発生しない値なので、Bottom型として扱えるなら、↑で書いたjustみたいな回りくどいことはしなくてよくなるけど
12:51 PM
そもそもその論調で行くならcase自体存在しないはずですよね、ということです。
12:51 PM
kotlin NothingはBottomでしたっけ、
Avatar
ボトムですね < Kotlin
12:52 PM
Bottom Never の実験するとき Kotlin 使ってます。
12:53 PM
まあSwiftじゃないので完全に同じじゃないですが。
Avatar
なるほど、Neverの定義がある場合はBottomかつデフォルトのNever値が呼ばれるなら確かに推論でどうにかなりそう (edited)
Avatar
Neverなcase、無視できたら良さそうですね〜。
Avatar
enum Enum2<T0, T1> { case case0(T0) case case1(T1) } func foo(x: Enum2<Int, Never>) -> Int { switch x { case .case0(let x): return x } } 9.0 beta3 でこれは通ります。
😀 1
Avatar
おお
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
12:43 AM
StringProtocol なるものが追加されたの初めて知った。
Avatar
Stringを引数に取る関数と拡張を、Substringでも使いたい、と
Avatar
みたいですね。
Avatar
あーそれほしいやつですね
Avatar
@Biacco42 Swift4使ってるの??
Avatar
@koher いや、まだ使ってないですけど、将来的に来るなら嬉しいなってやつです (edited)
🙂 1
Avatar
この間作ったenum-convertible、実際にはcase数NのEnumに対するtype-erasureなので
10:36 AM
AnyEnumとかのほうが良い気がしてきた
Avatar
AnySequence みたいに case 数 N の enum を渡せるんですっけ?
Avatar
convertible定義すれば、ですね
Avatar
変換用の initextension で足すということですか?
Avatar
extensionでasAnyEnumみたいなの書く感じですね
Avatar
うーん、それだとやっぱりちょっと AnySequence とは違う気もしますね〜。
Avatar
機能と目的は同じですが、生成方法が著しく違いますね
Avatar
AnySequence はラッパーなのに対して convert しているという構造上の違いが AnyEnum と呼ぶのにちょっと違うかなぁと感じますね。
Avatar
なるほど
Avatar
それに、 AnySequence みたいに型名も AnyEnum3 とかにすると長くなっちゃうし。
1:45 AM
今、「パッケージ名 EnumN とかだと短くて良かったかもですね」と言おうとして検索したら前にも言ってた😅 思考回路変わってない・・・。
Avatar
omochimetaru 7/20/2017 1:48 AM
AnySequenceはSequenceプロトコルを満たす型をなんでも変換してAnySequenceにできて、それ自身Sequenceとして使える、という型で、その際にSequenceのassociated typeをAnySequenceの型パラメータに移している。AnySequenceから個別のSequenceに戻すときにはコピーをする。 @tarunon が作っているのは(なんでもEnumと仮称)、「case数とcaseごとのassociated valueの型」が同一であるenum型をなんでも変換できる型で、個別のEnum型がもっていたassociated valueの型を、なんでもEnumの型パラメータに移す(個数は型名自体に移す)、個別のEnum型に戻すときはコピーをする。 (edited)
1:49 AM
できていることは同じに思うけど、そもそも「case数とassociated valueの型が同じEnum型同士」はプロトコルではないし、表現方法が同じだけで本質的に互換性は無いもの同士なので、どこで使うんだろう?
Avatar
そもそものモチベーションは、case数とassocvalueの型が保障されたprotocolが欲しい、と言うところで、それを取り扱うためには具体型としてのEnumNが必要だった、という感じ
1:52 AM
enumを定義するのはライブラリ提供者ではなく利用者だが、ライブラリ提供者は指定されたcaseとassocvalueを実装したenumを作って欲しい、と。
1:53 AM
もうちょっと掘り下げると、Equatable準拠とかライブラリ提供者側で出来ないから、定義を利用者に投げたいということ。
Avatar
omochimetaru 7/20/2017 1:54 AM
enumをAPIにしたいけどライブラリ側で定義するのだとユーザ側でライブラリを使うときに変換を用意しないといけないから、ライブラリがEnumNで組んでおくと、ユーザーはEnumNへの変換をセットアップすれば楽に使える? (edited)
Avatar
そんな感じやね
1:55 AM
ライブラリ側はEnumNConvertibleを引数に取るから、利用者はコンバート関数だけ作ればAPI使うときはコンバートもしなくて良い。
1:55 AM
EnumNはほぼ、switchの安全とコンバートを保障するためだけの具体型
Avatar
omochimetaru 7/20/2017 1:59 AM
APIから戻ってくるときは? EnumN -> ユーザ定義enum への変換
Avatar
それは特にないなぁ
2:00 AM
相互互換持たせるprotocolにする、単にinitを定義すれば、いけるとは思いますが
Avatar
omochimetaru 7/20/2017 2:00 AM
ユーザ定義enum -> EnumNへ変換する EnumNConvertibleを実装するときは、中身は switch case で普通に書くの?
Avatar
そう
Avatar
omochimetaru 7/20/2017 2:01 AM
だとすると、仮にライブラリAが、 enum LibAEnum を持っていたとしても、 protocol LibAEnumConvertible を定義していたら
2:02 AM
ユーザ定義enum -> EnumN の変換のために EnumNConvertible を書くのと ユーザ定義enum -> LibAEnum の変換のために LibAEnumConvertible を書くのは
2:02 AM
ユーザ側の手間は同じ?
Avatar
一緒やと思う
Avatar
omochimetaru 7/20/2017 2:02 AM
じゃあ、 EnumNConvertible -> EnumN のところが事前用意されているからライブラリ実装側が楽、という事?
Avatar
Convertible があるなら型名さえ AnyEnum3 等にすれば AnySquence とのアナロジーとしていいような気がしてきた。 (edited)
2:03 AM
前話したときも Convertible について話してたのに存在を忘れてた。
Avatar
protocolを引数に取れば良くなるからその通りかな?
2:04 AM
あとは、mapKとか、unwrappedとか、そういう便利関数を丸っと定義できるのも
Avatar
omochimetaru 7/20/2017 2:04 AM
ふむふむ
Avatar
unwrappedのNever対応計画は120万行のコードを残して霧散したけど
2:10 AM
確かに、EnumN→Covertibleの実装への変換も、あった方が良いな。追加しよう。
Avatar
それって Convertibleinit(_ x: Enum3<T0, T1, T2>) とかを足すってことですか? (edited)
Avatar
そうです
Avatar
swift-4.0-DEVELOPMENT-SNAPSHOT-2017-07-20-a
Avatar
いつのSNAPSHOTからかわからないけど、Xcode 9でIDEIndexEnableBoltIndex NOが不要になってた。 (edited)
Avatar
omochimetaru 7/25/2017 7:39 AM
var a: Int32 = -3 var b: UInt32 = UInt32(a) // EXC_BAD_INSTRUCTION var c: Int64 = Int64(Int32.max) * Int64(10) var d: Int32 = Int32(c) // EXC_BAD_INSTRUCTION 素晴らしい
7:39 AM
でも、例外やオプショナルじゃなくていいのかな・・・
7:40 AM
これがC++だと変な値になったまま動作を続けるので結構怖いバグを生みます。
Avatar
なんだっけ
7:41 AM
コンパイルオプションでImplicitly unwrapとか無視して突き進むやつ
7:41 AM
あれやったらどうなるの
Avatar
omochimetaru 7/25/2017 7:41 AM
-Ounchecked?
Avatar
そうそれ
Avatar
omochimetaru 7/25/2017 7:42 AM
[omochi@omochi-iMac int]$ swift -Ounchecked a.swift -3 4294967293 21474836470 -10
7:43 AM
var a: Int32 = -3 print(a) var b: UInt32 = UInt32(a) print(b) var c: Int64 = Int64(Int32.max) * Int64(10) print(c) var d: Int32 = Int32(c) print(d)
Avatar
precondition相当ですね
Avatar
omochimetaru 7/25/2017 7:43 AM
C++と同じ挙動か?
Avatar
これは Logic Failiure で適切だと思う。 (edited)
Avatar
うーむ?
12:08 PM
String to Int は Optional で、 Int64 to Int32 は Logic Failure であることに
12:08 PM
理由付けできるんでしょうか
12:08 PM
相対的なレベル感としては感覚的には納得できるけど。 (edited)
Avatar
基本的に桁あふれは起きないってスタンスだと思うんよね。
12:09 PM
桁を意識しないといけないのは特殊な状況で
Avatar
Int64を使う時点で当たり前のように起きるような?
Avatar
それの責任を持つのはプログラマ側。
Avatar
Int32 to UInt32 も、In32に負の数が入っていることもよくあると思う。
Avatar
init?(exactly:) があるんで、お好きな方をってことじゃないでしょか。
Avatar
Int32.max + 1 が Logic failure なのと同じな気が。
Avatar
おお、 exactly: は知らなかった。いいですね (edited)
12:11 PM
Int32.max + 1 が Logic failure なのと同じな気が。
それはなかなか起こらない気がするんだよな。Int32の中だけの出来事だから
Avatar
exactly (知らなかったけど)や &+ は用途に応じてそういう手段が提供されていて、標準ではオーバーフロー系は Logic failure で統一されてるんじゃないかな? (edited)
12:13 PM
Int(String) との比較で言えば、 conversion だと思えば同じに見えるかもしれないけど、 parse だと思えば異なるものな気が。
Avatar
ふーむ
12:14 PM
まあいいのか、どこからがlogic failureになるかはAPIごとの決めの問題でしかないか (edited)
Avatar
完全な正解はないから、ユースケースに応じて一番多そうなものに合わせて、後は他との類推が効きやすいように一貫線を持たせて決めるしかないと思う。
12:16 PM
String からのパースとの類推が聞きにくいという意味で少し微妙だったと。
12:17 PM
明確な線引がないという点では、 Arraysubscript とかだって、番兵とかを考えると Optional であってほしいという考えはあるけど、 Logic failure としてしまった方が適切なケースが多いという決めの問題でしかないと思う。
Avatar
norio_nomura 7/26/2017 7:28 AM
Objective-Cに書き直した方が速いものって何だろう? https://twitter.com/mkino/status/890102457992437761
Swiftでプログラム書く。 Instrumentsでパフォーマンス計測。 ホットスポットをObjective-Cで書いて高速化。 の流れ、ほんと好き。SwiftからObjective-Cへのダウンスケールが楽チンなのが素晴らしい。
7:28 AM
多次元配列操作とかかな。
Avatar
C/C++の多次元配列相当のものはstructで作れそう。
Avatar
そういえばなんでコレやってないんだろうと思って検索したら出てきたネタ。 https://bugs.swift.org/browse/SR-4007 (edited)
9:19 AM
現状 String は64bit環境で24バイトだから、22バイトくらいまでだったらバッファ確保せずに Stringstruct に格納出来るようになって欲しいな。
Avatar
norio_nomura 7/26/2017 1:41 PM
tagged pointerのおかげでObjective-Cの方が速いものがある?
Avatar
omochimetaru 7/26/2017 1:53 PM
NSNumberとかで使われてるんですね。そういうケースなら普通に値型の数値使えば良さそうだし、この人の想定がどういうものなのかは聞いてみないとわからなさそう。
1:54 PM
SSOは効果ありそうだし、String使いやすくするやつ達成した後ぐらいに入りそうだ。
Avatar
そういえばswitch case 文で取ったら値をさらにもう一回アンラップすることって可能ですか?例えば enum A { case a(Int?) } let a = A.a(1) switch a { case .a(let a) where case .some(let unwrappedA) = a: //do something default: break } みたいな
Avatar
case .a(.some(let x)): かな?
Avatar
おお!ありがとうございます!!
Avatar
case .a(let x?):でもっと楽にいけませんか
😘 1
Avatar
omochimetaru 7/27/2017 3:19 AM
@tarunon は let 内側派なの
Avatar
内側派だわ
Avatar
omochimetaru 7/27/2017 3:20 AM
ワイ case let 主義派 (edited)
Avatar
それ二変数だとどうなるの?書いてないから知らないんだけど
Avatar
僕も内側はですね
Avatar
二変数もできたはず
Avatar
二変数でlet一回なら乗り換える
Avatar
omochimetaru 7/27/2017 3:21 AM
enum EE { case a(Int, Int) case b } let ee = EE.a(7, 9) switch ee { case let .a(x, y): print(x, y) default: break } /* output 7 9 */ (edited)
Avatar
乗り換えよう、ありがとう
Avatar
omochimetaru 7/27/2017 3:22 AM
いまplaygroundでチェックした。
3:22 AM
乗り換えさせてしまったw
Avatar
case let は変数がある場合とない場合 case let .case . が混在するのが微妙に気持ち悪くて…w
Avatar
常にcase .で揃えたくて内側という人はいそう。僕は外側派です
😀 1
3:23 AM
let何回も書きたくない派ですね
Avatar
気持ちはわかる、だから if case let . は外側で書いてますw
Avatar
omochimetaru 7/27/2017 3:25 AM
僕は「変数を作るんじゃい!」って大事なことだから目立ったほうがいいという感じ(後ろの方はぼやけて見えない
Avatar
case .a(let .some(a)): これもできたので揃えつつ省略はできそう
Avatar
omochimetaru 7/27/2017 3:25 AM
中間派きた
Avatar
let x = 12 switch ee { case let .a(x, y): print(x, y) default: break } みたいなときに x が何を指しているのか不安になるので 内側派。 (edited)
Avatar
tab vs spaceじみてきた
Avatar
シンボルの宣言がどれなのか分かりにくいってのはありますね
Avatar
宗教戦争
Avatar
omochimetaru 7/27/2017 3:26 AM
@rintaro それは不安だ・・・
Avatar
内側派 rintaroさんの意見にしっくりきました
Avatar
お内側派の仲間増える?
Avatar
まあ最近は別にぶれててもええやろと思ってます。適材適所と、チームの人による。
👍 3
Avatar
「マッチしたのはこのケースだよ」「使うのはこの変数だよ」って順番が整然としてたほうが個人的には好き
Avatar
norio_nomura 7/27/2017 3:45 AM
rintaroさんの例に「そんな変数名使うな」という意見が出ない不思議。
Avatar
変数名の問題というより、実際バインディングではなく外側の値にマッチさせたい場合に case .foo(x, let y) と書かなければいけないので、最初から内側で統一しておいたほうが楽かなと思うのです。
Avatar
norio_nomura 7/27/2017 6:34 AM
あああ、なるほどです。
6:34 AM
よくわかっていませんでした、ありがとうございます。
6:39 AM
caseで変数とマッチさせる書き方って、あまりやった記憶がないな。
6:43 AM
where使っちゃう。
Avatar
逆にこの挙動をわかってて、変数にマッチさせない、もしくは where 使うっていうルールがあるなら、 外側 let で統一して let 忘れを防ぐっていう考え方もありかと。
Avatar
norio_nomura 7/27/2017 6:47 AM
あと、バインドとマッチを混ぜるという発想がなかったです
Avatar
caseで変数とマッチさせる書き方って、あまりやった記憶がないな。
これ+もう片方に変数使いたいのがあるってかなりレアケースになりそうな
Avatar
実際 let a, b : Int a = 1 b = 2 できるから case .foo(let a, b): も両方バインディング扱いだろうと思っちゃうと、 b が外側にあったときにバグに気づけなくて悲劇が起こりそう。 外側 let のほうが良い気がしてきたw
Avatar
norio_nomura 7/27/2017 6:55 AM
そうか、こんな書き方できるのか。 enum EE { case a(Int, Int) } let ee = EE.a(12, 1) if case let .a(12, y) = ee { print(y) }
Avatar
omochimetaru 7/27/2017 6:55 AM
let a, b : Int のときは letが "a, b"にかかるけど case .foo(let a, b): のときは letが aだけにかかるということか
👌 1
Avatar
norio_nomura 7/27/2017 7:00 AM
無駄にバインドとマッチを混ぜて使ってみたくなる。
Avatar
norio_nomura 7/27/2017 7:07 AM
バインドとリテラルへのマッチは混ぜて使ってた。
7:07 AM
変数へのマッチがなかった。
Avatar
do { let x = true let y = false enum Foo { case hoge(Bool) case fuga } let foo = Foo.hoge(x) switch foo { case .hoge(x): print(x) case .hoge(y): print(y) case .fuga: print("fuga") } } /* error: MyPlayground.playground:6:5: error: switch must be exhaustive switch foo { ^ MyPlayground.playground:6:5: note: add missing case: '.hoge(_)' switch foo { ^ */ 変数へのマッチで思いついたけど、流石にこれは面倒見てくれないかw
Avatar
それね、BoolとIntの網羅性チェックがまだ完璧じゃないんですよな…
Avatar
このへんって変数でも網羅チェックしてくれるのが良いんですかね? var x, yだったりしたら大変そう。
Avatar
x,yは微妙だけど、xと!xはやって欲しいかな。試してないけど出来るかしら
2:44 AM
varはやらなくてよさそう。letだけで良いと思う。 @t.ae
Avatar
以前の..<0, 0, 0<..もですけど評価しないと網羅性の保証ができないのはどうなんだろうと思います。
Avatar
omochimetaru 7/28/2017 2:46 AM
リテラルだって評価は評価だから
Avatar
確かに。
Avatar
まあでもenumは網羅性チェック簡単だからできるとして、実際Intの網羅性チェックってどうやって実現できるでしょ?
Avatar
omochimetaru 7/28/2017 2:47 AM
C++11ではそういう用途のために constexpr っていう仕組みが入った
Avatar
流石に64bit全パターンチェックするわけには行かないでしょうし
Avatar
omochimetaru 7/28/2017 2:47 AM
コンパイル時に計算することを保証させる型
2:47 AM
constexpr は constexpr な式からしか構築できないようになってて
2:48 AM
コンパイル時に定数扱いになる
Avatar
それだとx, !xはできなそうですね
2:49 AM
xによるか
Avatar
omochimetaru 7/28/2017 2:50 AM
Boolの x と !x による網羅はできないね
2:50 AM
1 - 0 か 0 - 1か不確定だけど網羅されることは保証できるっていうのはもっと難しいタスクになるね
2:51 AM
@lovee 範囲で切っていけば ..<0 , 0 <.. は全然できると思うよ
Avatar
@omochimetaru まず <.. 演算子を作ることからですね(ry
Avatar
omochimetaru 7/28/2017 2:51 AM
Avatar
網羅性チェックで思い出したけど、分野は全然違うけどAuto Layoutの制約をコードで描くときもAmbiguousチェックできてないですよね今、あれもクソだと思う
Avatar
omochimetaru 7/28/2017 2:56 AM
実行時にも曖昧だとログでないですっけ?
Avatar
実行時は出ます
Avatar
omochimetaru 7/28/2017 2:57 AM
ああ。
Avatar
でもコンパイル時に出して欲しい。
2:57 AM
まあ俺Auto Layout使わないから別にどうでもいいけど()
Avatar
structのすべてのプロパティが一致するときにequalであるとしたいときにEquatableに適合するために==オペレータを定義してその中で全部のプロパティ同士を比較するみたいなことをやるとあとからプロパティが追加されたときに==オペレータにそれの比較が漏れがちというのを仕組みで防ぐ方法ってなんかないでしょうか〜
Avatar
omochimetaru 7/31/2017 1:24 AM
あーそれね・・・無さそう・・・
1:28 AM
Codableなら自動で全プロパティを舐められるから、Codable使ってJSONにして、JSON文字列同士の完全一致で比較すると、一応そのミス自体は防げそう。 JSONだと重いからなんらかのバイナリフォーマットのほうがいいかもしれんけど、 実際 == 演算子並べるほうのがベスト
Avatar
EquatableもCodableよろしくある程度自動生成してほしい
Avatar
それってJSONでなくてもCodable使ってできない?
Avatar
omochimetaru 7/31/2017 1:29 AM
それってJSONでなくてもCodable使ってできない?
はい、できるので、なんらかのバイナリフォーマットのほうがいいかもしれないけど
1:30 AM
大体の場合でJSON化はAPI連携都合ですでにあったりするので
Avatar
全propertyがEquatableなら省略可、ぐらいで
Avatar
omochimetaru 7/31/2017 1:30 AM
とりあえずやるならJSONが楽かなと。
Avatar
protocol AutoEquatable: Codable, Equatable って作れないかな?
Avatar
omochimetaru 7/31/2017 1:31 AM
あ、シリアライズするんじゃなくて、
1:31 AM
Codableの機構をそのまま使えないかってこと?
Avatar
うん、そう。
1:32 AM
あー、でも全プロパティが Equatable であることが保証されてないから難しい?
1:39 AM
これは Codable を使うのではなく、実装を Codable の様に生成させるやつだった。
Avatar
omochimetaru 7/31/2017 1:39 AM
言語機能としてはそっちのほうが本命ですね
Avatar
> Hmm, I can see the appeal of automatically deriving Equatable and Hashable conformance, but I'd like that to be opt-in. That is, types should declare that they are Equatable or Hashable to begin with. It wouldn't have to take extra syntax, as compiler magic could effectively synthesize default implementations for == and/or hashValue when all members are themselves Equatable or Hashable, respectively. With such a scheme, consideration can be made to accommodating classes too. Completely agreed. -- Chris Lattner
1:40 AM
Please follow the precedent of the Codable proposal as closely as possible. If you’d like this to be successful for Swift 4, you should look to scope it as narrowly as possible. Because it is additive (with opt-in), it can always be extended in the future. -- Chris Lattner
Avatar
omochimetaru 7/31/2017 1:40 AM
あ、この返信見たの思い出してきた
Avatar
CodableEquatable なら通りそう?
1:42 AM
PR も
1:42 AM
そうなってるのかな?
Avatar
norio_nomura 7/31/2017 1:42 AM
実装のPR もある https://github.com/apple/swift/pull/9619 (edited)
This is the implementation of the yet-to-be-merged/reviewed evolution proposal to synthesize Equatable/Hashable for enums with payloads and for structs (apple/swift-evolution#706). I'm offering thi...
Avatar
swift-evolutionの方のPR ざっと見る限り Codable と同じようにデフォルト実装の生成になってて良さそうな気がするんですけどなんで放置状態なんでしょう?
1:53 AM
Codable の自動生成を認めた以上、これも問題なさそう。
Avatar
omochimetaru 7/31/2017 3:11 AM
protocol で let 強制したいなあ.
@tarunon @omochimetaru var get, readonly であって immutable ではないというのはそうなんですけど, immutable なのを強制したいなあという話でした.
3:12 AM
Swiftのprotocolだと readonly な getter を宣言できるけど、 immutable な getter (フィールド?) を宣言する機能がほしいなあという話題があった
Avatar
それより protocol をネストできるようにして欲しい
3:14 AM
いつもいつも XxxxxxxxxDelegate みたいな名前になってクッソ長すぎ
Avatar
omochimetaru 7/31/2017 3:14 AM
個人的にも欲しいと思ったことはあるけど、なんとなく、それができちゃいけない気もするが、理論的に整理できてない
3:15 AM
@lovee プロトコルがネストできる構文にしようとすると、 static func とかと整合性を取りにくいんですよね
Avatar
仮に出来ると仮定してprotocolにprotocolをネストした場合は何が起こるべきなのか
Avatar
omochimetaru 7/31/2017 3:15 AM
@lovee さんが求めているのは単に名前的な階層化なんだろうけど
Avatar
rustのgenerics traitみたいになるべきなのか
Avatar
omochimetaru 7/31/2017 3:15 AM
static func との一貫性を考えると、「conformanceする型に対するネストタイプをもつべきという制約」
3:15 AM
に見えちゃって微妙なんだよね
Avatar
そうですね、 protocol をネームスペースに入れたいっていうのが大きな理由ですかね
Avatar
structやclassの中にprotocolを宣言できるとして、直感的には高階型と似た枠組みになる気がしている (edited)
3:19 AM
いや似てないか
Avatar
omochimetaru 7/31/2017 3:19 AM
今って struct の中の protocol も駄目なんですね
3:20 AM
protocol の中の protocol のことを考えてました。
Avatar
protocol のなかに protocol はまあ面倒そうですね
Avatar
omochimetaru 7/31/2017 3:20 AM
struct HogeView { protocol Delegate { ... } } class Cat : HogeView.Delegate { ... } これすら駄目と
Avatar
ダメです
3:21 AM
そこが辛い
Avatar
omochimetaru 7/31/2017 3:21 AM
確かにつらい
3:21 AM
(完全に話題フォークしたな)
Avatar
struct Hoge<Foo> { protocol Delegate { //ここはFooが使えるべきだが… } } (edited)
3:22 AM
こういうことになるので今は無理かと
Avatar
omochimetaru 7/31/2017 3:23 AM
その場合は
3:23 AM
Hoge<Int>.DelegateHoge<String>.Delegate は完全に独立な別々の型ってことでいいんじゃない?
Avatar
あとまあ DataSource プロトコルにビューを隠蔽したい気持ちもある protocol XxxViewDataSource { func numberOfCells(in view: XxxView) -> Int } ではなく protocol XxxViewDataSource { protocol Sender: class { } func numberOfCells(in view: Sender) -> Int } みたいな感じにしたい
Avatar
omochimetaru 7/31/2017 3:23 AM
protocol HogeIntDelegateprotocol HogeStringDelegate が定義されているものと考えればよし
Avatar
うーん
3:26 AM
class My {} extension My: Hoge<String>.Delegate extension My: Hoge<Int>.Delegate こういうことになるわけだけど
3:26 AM
rustのtrait相当の操作も可能になる、ということ?
Avatar
omochimetaru 7/31/2017 3:26 AM
メソッド名が完全に衝突する?
3:26 AM
事実上RustのGeneric Traitと同じ事になるね
3:26 AM
今ってメソッド名が衝突するプロトコルってどうなんだっけ
Avatar
型が違えばオーバーロード、同じで2つ存在したらambiguousでコンパイルエラーかな (edited)
Avatar
omochimetaru 7/31/2017 3:27 AM
protocol P1 { func aa() -> Int } protocol P2 { func aa() -> Int } class Cat : P1, P2 { func aa() -> Int { return 33 } } Cat().aa()
3:27 AM
普通に動くんやな
3:28 AM
別々の実装を用意することができない、のか。
Avatar
今でも普通に extension Array が使えるから別に問題ないじゃないかと…?
Avatar
omochimetaru 7/31/2017 3:31 AM
extension Arrayはメソッドは定義できるけど
3:31 AM
その内側にプロトコルは定義できないから
3:31 AM
これがプロトコル定義できるとなると話が広がっていきますね
Avatar
@omochimetaru いいえ、 extension My: Hoge<String>.Delegate の話です
3:32 AM
多分それは普通に extension My: Hoge.Delegate でも問題ないんじゃないかと、associatedType で使えるはずなので
Avatar
この場合のassociated typeとgenericsは別であるべき、だと思います
3:36 AM
それはそれとして、3.0時代までgenericsはネストした型が作れないとかあったんで、generics無しの場合だけprotocol作れる、と言う時期があっても良いかもしれない。
Avatar
omochimetaru 7/31/2017 3:36 AM
My: Hoge.Delegate がもしできちゃうとすると、 struct Hoge<T> { protocol Delegate { func a() -> T } } extension My: Hoge.Delegate { func a() -> ??? { ... } } ってなってたときに、 T がわからなくて困るよ。 (edited)
Avatar
Tはassoctypeと見做せるでしょ、という話
Avatar
omochimetaru 7/31/2017 3:37 AM
埋めた型が Hoge<T> の Tに逆伝搬するってことか。
Avatar
ただ、現状のネストしたgenerics型の振る舞いから予想すると、assoctypeにはなれない気がする
Avatar
omochimetaru 7/31/2017 3:40 AM
Genericsは型の生成で、protocolのassociatedtypeはすでに生成されている型のマッチングで、意味が違うと思う
Avatar
Chris Lattner が興味深いこと↓を言ってる。 I tend to prefer that exploration in this space happen in order of points above, and would prefer not to get to a generalized macro system for a couple of years - just to give Swift more time to mature and develop without it. Other languages have gotten macro systems too early in their development, and become too reliant on it. Perhaps if C didn’t have one it would have ended up with a proper import mechanism. Perhaps if Rust didn’t have one, some of its decisions would have been different. etc.
Avatar
"constexpr" for Swift 5のスレですね
Avatar
omochimetaru 7/31/2017 5:22 AM
英語難しい・・・ CやRustはマクロを入れるのが早すぎてそれに頼りすぎて微妙になった、Swiftにはまだ早い って言ってる?
Avatar
このちょっと前に I’m a fan of eventually adding a very general, but still hygienic, macro system at some point ってのがあって、マクロ自体はあったらいいと思うけど Swift には時期尚早だと。
8:00 AM
早い段階でマクロを入れるとマクロに依存しすぎるから、言語が成熟するまで待った方がいいと考えてる。くらいの意味合いかと思います。 (edited)
Avatar
omochimetaru 7/31/2017 8:06 AM
その意見は完全に同意です
8:08 AM
マクロに頼らずとも言語機能でできることを少しずつ決めていって、できればそれで済ませて、
8:09 AM
どうしてもはみ出すことだけマクロでやるようにしないと
Avatar
うん。
Avatar
omochimetaru 7/31/2017 8:09 AM
黒魔術が氾濫していろいろつらくなる
8:09 AM
Rustはtry-catch的なものとかprintlnまでマクロですね
Avatar
↓も興味深い。 4) The macro system should eventually support unstructured compile time expansion, along the lines of what people do with Gyb and Sourcery with all the tradeoffs they bring.
Avatar
コード生成機能がコンパイラに乗って、gybが無い世界が理想だけどそれをやるにはまだはやい
Avatar
gyb が要らない世界楽しみ。
Avatar
多分後方互換性が手に入った後が妥当なんじゃないですかね
Avatar
ですね。今は ABI ですら安定していない・・・
Avatar
ABI安定前にmacro導入は死の香りしかしないw
Avatar
omochimetaru 7/31/2017 8:15 AM
むしろマクロはソース生成レベルの仕組みだから
8:15 AM
ABIは関係ないのでは
8:15 AM
言語仕様レベルで互換性が取れてれば。
Avatar
うん、論理的には直交してると思う
Avatar
言語機能として何が足されるか、何が消えるのかが見えてない状態でmacroがあると
8:16 AM
死んだコードの山になる気がしている
Avatar
ただ、ステップとしては、まず ABI 安定化して、それから構文を固めていこうって流れなのでは。
Avatar
まあ死ぬのはどっちにしても、か
Avatar
omochimetaru 7/31/2017 8:16 AM
ああ、なるほど。
8:16 AM
可変長引数ジェネリクスとかまさにそうだね
Avatar
そうそう
Avatar
omochimetaru 7/31/2017 8:17 AM
まあ手で書いててもゴミになってしまうのは同じやね (edited)
8:17 AM
っていうかCodableが完全にソレか
Avatar
omochimetaru 8/2/2017 6:52 AM
お!MLスレだ
Avatar
まだすぐには進まなさそうだけど、完全無視状態よりは前進か。
Avatar
ML (Mailing List, Machine Language, Machine Learning) でどれだ!ってなる
6:53 AM
Swiftだと高確率でMailing Listかなw
Avatar
omochimetaru 8/2/2017 6:54 AM
MLをフォーラムに移行する話題
Avatar
してほしいですね
6:56 AM
discourse - A platform for community discussion. Free, open, simple.
6:56 AM
これ使うのか
Avatar
norio_nomura 8/4/2017 2:09 AM
サードパーティーのEncoderDecoderOptionalCodableをうまく扱えない不具合の回避方法を見つけて修正してもらったのですが、もうSwift 4.0リリースには入れられないと言われてしまった。 https://bugs.swift.org/browse/SR-5206 (edited)
😢 4
Avatar
えぇ…
2:09 AM
Swift4.1待ちの流れ
Avatar
Conditional Conformance も Swift 4 に入らないんですか?
2:12 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
norio_nomura 8/4/2017 2:12 AM
入らないかと。
Avatar
入るのかと思ってました・・・。辛い・・・。
Avatar
辛い…
Avatar
じゃあ↓もできないままなんですね・・・。 extension Optional: Codable where Wrapped: Codable {} (edited)
2:14 AM
実行時に弾くまま・・・。
Avatar
norio_nomura 8/4/2017 2:15 AM
件のissueもConditional Conformanceがこないと回避できないという認識だったのですが、せっかく回避できたので、もう一度Swift 4.0に入らないか質問してはみました。
2:19 AM
もっと早くにCoderの実装を最新へ追随させる作業をしていたなら、回避方法も早くに見つけていてSwift 4.0へも入っていたかもしれず、ちょっと後悔。
Avatar
norio_nomura 8/4/2017 2:55 AM
[swift-evolution] Why you can't make someone else's class Decodable: a long-winded explanation of 'required' initializers https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170731/038522.html Codableのinitializerについての話。スレッドを追うとFactory initializer要るよね〜な話にもなっていく。 (edited)
Avatar
Codable入れるの時期尚早だったのではと言う気がしてくる
3:01 AM
どうしても、Conditional Conformanceありきだと思ってしまう
Avatar
Codable より先に Conditional Conformance やってほしかった・・・
Avatar
norio_nomura 8/4/2017 6:25 AM
SE-0166 Swift Archival & SerializationはImplementedになってるけど、SE-0167 Swift EncodersはまだImplementedになってないですね。
Avatar
まだ実装されてないものがあるんですか?単なる更新し忘れ?
Avatar
前に Range 同士の contains を実装してここで書いたやつ間違えてた。↓の条件が複雑だった。 let a: ClosedRange<Int> = 2...7 let b: Range<Int> = 3..<8 a.contains(b) // true let a: ClosedRange<Float> = 2...7 let b: Range<Float> = 3..<8 a.contains(b) // false
8:24 AM
8:29 AM
EasyImagy - Makes it easy to deal with images in Swift
Avatar
テスト自体をgybで吐き出してるのか、なるほど
Avatar
テスト吐き出してひっかかって実装がまずいことに気づきました。テストの大事さが身にしみる・・・。
8:32 AM
テスト吐く場合はそのロジックが間違えてないことが重要ですが、書き下されたものを一応目視でチェックしました。
Avatar
テストをgybで作るとなると、生成コードの方の妥当性が気になってしまう
Avatar
omochimetaru 8/4/2017 8:33 AM
俺もそう思ったけど
Avatar
なんか
Avatar
omochimetaru 8/4/2017 8:33 AM
まあ両方間違える可能性は
8:33 AM
片方しかない場合よりだいぶ低いから
Avatar
帰納法的な証明ができればそれで良いのかなと思ったり
Avatar
omochimetaru 8/4/2017 8:33 AM
実装かテストのどっちでミスしてれば何かしら気がつけると思った
Avatar
最小ケースと、任意のnが正しい時にn+1が正しければ
8:34 AM
全てが正しいことを証明できるので、そんな感じのテスト
8:34 AM
任意のnが正しいという仮定をどうやって表現するか、かな
Avatar
omochimetaru 8/4/2017 8:35 AM
任意のnが正しい時にn+1が正しければ
これは内部のロジックを検査しないといけないから結局網羅的になるんじゃないか
8:35 AM
n = 3のときだけバグる、みたいな可能性が残る
Avatar
↑は境界チェックがメインですが、型の数が 4x4 で膨大なのでそれでもパターンが多すぎてとても手で書けません。
8:36 AM
満たしてほしい性質を記述することはできるから、それを書いて組み合わせ分を生成しています。
8:36 AM
逆に手で書こうとすると絶対にどこかミスってテストがバグると思います。
8:36 AM
もちろん生成コードがバグってる可能性はあるので
8:37 AM
吐き出されたコードを眺めて自分の思い描いていた条件を再現できているかはチェックが必要です。
8:40 AM
もし 2<..5 とか 2<..<5 とかも追加されたら地獄だ・・・。
Avatar
containsは便利そうだし実装もそれなりにでかいので単体ライブラリにしても良い気がしますがどうでしょう?
Avatar
evolutionにproposalでも良いのではとか思った
Avatar
@t.ae 切り出してもいいと考えてますが、 EasyImagy に依存性は作りたくないので EasyImagy はこのままですね。
8:41 AM
evolution はありですね。
Avatar
依存性は微妙なところですよね……
Avatar
omochimetaru 8/4/2017 8:42 AM
@koher も依存性は作りたくないという気持ちあったんだ
Avatar
なにせこの containsinternal に使ってるだけだからね。
8:43 AM
internal な dependency を記述できたらいいのになぁ。ライブラリをすべて internal 扱いで読み込めて衝突も避けられるような。
Avatar
omochimetaru 8/4/2017 8:44 AM
あーそれはよく思います
8:45 AM
swift-package-manager - The Package Manager for the Swift Programming Language
8:45 AM
SPMはめちゃめちゃターゲット切ってますよ
Avatar
SwiftPM って自身を SwiftPM で管理してるんだ・・・
Avatar
omochimetaru 8/4/2017 8:46 AM
ですね
8:46 AM
ただ現状だとターゲット名がSwiftのパッケージ名になっちゃってて、パッケージ内パッケージ名ではないので
Avatar
Swift 自体もいつかセルフホスティングな言語になるのかな?
Avatar
omochimetaru 8/4/2017 8:47 AM
import Basic とか書いてあって
8:47 AM
どーなのそれは・・・ って気持ちになる
Avatar
Contribute to range-contains development by creating an account on GitHub.
Avatar
omochimetaru 8/4/2017 9:24 AM
結局そうなるんですね
Avatar
いや、 EasyImagy はこれに依存させないです。 (edited)
9:24 AM
swift-evolution に投げるための説明資料。
Avatar
omochimetaru 8/4/2017 9:25 AM
おお。
Avatar
あれ? Array とか ArraySlicesubscriptClosedRange 等( Range 以外)をとるバージョンがドキュメントで見つからないんだけどどこ由来なんだろう? let a = [0, 1, 2, 3, 4, 5] let b = a[2...4] let r: CountableRange<Int> = 2..<5 a[r] // OK: [2, 3, 4] b[r] // OK: [2, 3, 4] let r2: ClosedRange<Int> = 2...4 a[r2] // OK: [2, 3, 4] b[r2] // OK: [2, 3, 4] (edited)
9:49 AM
実装も見つけられない・・・。
Avatar
いや、ちがうか? swift-3.1-branch にはそれっぽいのが無い。
Avatar
norio_nomura 8/5/2017 12:46 AM
bugs.swift.org へコメント書こうと思ったら swift.org メンテナンス中だった。
Avatar
@rintaro おおっ、ありがとうございます!
1:16 AM
typealias Indexable = _Indexable で、 _Indexable 等の underscored な型はドキュメントに記載がないからドキュメント上で subscript(bounds: ClosedRange<Index>) 等が抜け落ちてしまってる?? https://developer.apple.com/documentation/swift/indexable
Avatar
Collection.Indexの記述がどこにもなくて、Indexを引数に取る幾つかの関数が、良く解らないものを引数に取ってるみたいなの
1:18 AM
あった気がする
1:19 AM
4月3日にちょっとだけ話題に出してます
Avatar
日付指定で遡れるんですっけ? Discord
Avatar
Collectionで検索して、4月3日を探すしかないと思う
Avatar
tarunon Collection における不可視の `Index` と似た何かな?と思った って確かにありますね。
Avatar
その辺ですね
Avatar
Discord の検索、結構優秀ですよね。パーマリンクがないのは辛いけど。
Avatar
パーマリンクは欲しいですねw
1:23 AM
検索は優秀
Avatar
omochimetaru 8/7/2017 1:39 AM
Allow linking directly to a message. If someone posts something good... allow to get a link that will take the client directly to that message.
1:39 AM
これかなあ?
Avatar
ぽい
1:40 AM
Voteしとこ
Avatar
omochimetaru 8/7/2017 1:40 AM
公式フォーラムに要望掲示板があってVOTE機能がある
Avatar
omochimetaru 8/8/2017 2:04 AM
コーディング規約は全社で共通のがドン❗とあるよりプロジェクトごとにある程度散ってたほうが規約に対してコミットしやすいしなんとなくいい気がするけど確信がないから試しにこのプロジェクトではこう書いてみよっかみたいな小さな導入ができるのでいいと思うんだけどだめかなあ
Avatar
でたなキュレーター
Avatar
全社ドンが良い部分と、pj毎にやった方が良い部分があるのでハイブリッドが良さそう
Avatar
omochimetaru 8/8/2017 2:05 AM
同じ意見で、プロジェクトごとにいろいろやってみたい そこから知見を保守的に抽出して全社基準は作っといたらいいけど
Avatar
tab vs spaceとかブロックの改行とかは全社で揃えた方が良い
Avatar
それはそう、全社で共通して使われるべきベースみたいなのはあるべき
2:07 AM
そうか、そこはちゃんと書いてなかったけど、あくまで全体である程度統一されたルールはあるべきと思っているが、規約をちょっと変えてみようと思ったときにコミットする先がいきなり全社で使ってるルールだとハードル高いよね、だったらまずは手元のプロジェクトにだけ適用してよさげだったら全社のにフィードバックするみたいなのがいいよね、という意見
Avatar
規約にpr投げれる環境があった方が良いのはあるだろうなぁ
2:08 AM
社の規約があってpjはforkしてて、たまに社の規約にpr投げれるのが理想って事? @hiragram
Avatar
社のやつにどうフィードバックするかは正直どうでもいいかなって気がしていて、最大公約数的な全社の規約に縛られた結果いろんなプロジェクトが微妙なスピードになるくらいだったら、うちのプロジェクトはこう書くのが効率がいいっていうのをどんどん取り入れていって、他のプロジェクトにも還元できるならあとで全社のに追加すればいいんでね、って感じ
Avatar
規約がリポジトリになってれば、 fork して改造、運用後よければ PR というフローがいけいそう。
2:10 AM
GitHub とか GHE 使ってる想定で。
Avatar
@koher それって各プロジェクト用のコード規約が独立したリポジトリにいる感じになりますか?
Avatar
それはそうなっちゃいますね。
Avatar
それもまたコミットへのめんどくささという障壁になる気がしていて、だったらアプリのソースのリポジトリにmarkdown1個コミットしちゃえばいいんでね派です
Avatar
サブモジュールでプロジェクト用のリポジトリには入れられるかもw
Avatar
「コミットしやすくするのは大事だが、そんなに全社のにガンガンフィードバックしまくるようなものでもないでしょ」というダブスタっぽい感じになってしまった
Avatar
omochimetaru 8/8/2017 2:12 AM
styleguide - Cookpad's coding style guides
2:12 AM
たしかクッパ社は全社のを外部に公開している (edited)
Avatar
有名なのは↓もあるよ。 https://github.com/github/swift-style-guide
swift-style-guide - Style guide & coding conventions for Swift projects
Avatar
うちもだしてるお
Avatar

はじめに

Swiftのコードは多様な記述の仕方ができるので柔軟でかつ表現力もありますが、チームで開発を行うとどうしても記述の仕方が統一できず可読性も上がりません。弊社([Wantedly](https://www.wante...
Avatar
omochimetaru 8/8/2017 2:13 AM
@hiragram アドレスはって
Avatar
「ちょっと規約いじりたいな」ってなっているときに他のプロジェクトのことを気にしなくていいほうが嬉しい、というのがあのツイートの発端
2:13 AM
はる
2:14 AM
こんにちは。iOSエンジニアの遠藤です。 今回はiOSチームでの実装規約について紹介したいと思います。 Swiftのコーディングについてだけではなく、実装する上での細かい約束事をまとめました。 参考になれば幸いです。
Avatar
omochimetaru 8/8/2017 2:15 AM
Contribute to style_guide development by creating an account on GitHub.
2:15 AM
こっちかな
Avatar
repoはそれ
Avatar
あー
Avatar
omochimetaru 8/8/2017 2:17 AM
結構みんな独自にゴリゴリ書いてるんだね 同じ項目も多いけど
Avatar
protocolの実装をextensionにわける、共感あるんだけど、これSwift4で死にそう
2:17 AM
extensionでoverrideできなくなるので
Avatar
omochimetaru 8/8/2017 2:17 AM
コーディング規約のフォーマット自体がバラバラなのが気持ち悪く感じてきたw
Avatar
エッジケースで死ぬ
Avatar
(規約そのものの話をしたかったわけじゃないんだけどなw)
Avatar
omochimetaru 8/8/2017 2:18 AM
規約の内容じゃなくて規約を記述した文書のフォーマットね。
Avatar
各社が自慢のコーディング規約を公開する統一フォーマットQiitaみたいなのがほしい
Avatar
omochimetaru 8/8/2017 2:18 AM
そうそう。
2:19 AM
それで、機械的に差分が出たりしたら
2:19 AM
とても参考になりそうだ
Avatar
お、コーディング規約を投稿するサービスを作ればいいのでは
2:19 AM
各種言語の
Avatar
どうせならLintまでやって欲しいんだよなぁ
Avatar
でも Python とか PEP8 か
Avatar
omochimetaru 8/8/2017 2:19 AM
Swiftだけでいいよ
Avatar
guardの中身のreturnを同じ行に書く企業 で絞り込めたりしたら面白そう
Avatar
return なら 1 行で書くなぁ。 < guard
Avatar
omochimetaru 8/8/2017 2:20 AM
guard 改行しなかったことない
Avatar
僕は開業しますね
2:20 AM
改行
Avatar
規約はlintと存在理由のコメントのペアの文書で表現して、コンパイラに食わせたら全部やって欲しい
Avatar
改行無しの{}はクロージャっぽく感じる (edited)
2:21 AM
でも defer 一行は改行しないなぁ (edited)
Avatar
lint 用の制約として変換できる読みやすいフォーマットがいいのかも
Avatar
lint もいいけど、もっと進んでまともな formatter が Xcode にインテグレートされて欲しい。
Avatar
サーバーサイドSwiftで作るSwiftコーディング規約サイト
Avatar
omochimetaru 8/8/2017 2:23 AM
もっと進んでまともな formatter が Xcode にインテグレートされて欲しい。
ほしい
2:23 AM
SSSSCSSじゃん (Server Side Swift Swift Coding Style Site) (edited)
Avatar
CSSを地獄ほど拡張したやつっぽくてなんか嫌
Avatar
omochimetaru 8/8/2017 2:25 AM
ww
Avatar
norio_nomura 8/8/2017 2:40 AM
みんなSwiftLint使ってるのかな?
Avatar
omochimetaru 8/8/2017 2:41 AM
僕はノッてきたら使ってます
Avatar
開幕podに入れてる
Avatar
omochimetaru 8/8/2017 2:41 AM
ある程度できてきたらそろそろきれいにするか〜みたいな
Avatar
ルールが用意されてれば使う、独自の規約をLintルールにするところまでは全然やってなそうな印象
Avatar
norio_nomura 8/8/2017 2:43 AM
swiftlint lint --sssscss-identifier githubみたいな
Avatar
アプリは使うけどライブラリは使ってないな
Avatar
sssscss-identifier❗
2:44 AM
なるほどそういうことかw
Avatar
norio_nomura 8/8/2017 2:46 AM
swiftlint lint --config https://github/github/swift-style-guide.swiftlint.yml みたいなことが出来れば良さげ。
2:51 AM
lint もいいけど、もっと進んでまともな formatter が Xcode にインテグレートされて欲しい。 これが育っていけばいずれは… https://github.com/apple/swift/pull/11320
⚠️ Do Not Merge ⚠️ This patch is an initial implementation of the Swift libSyntax API. It aims to provide all features of the C++ API but exposed to Swift. It currently resides in SwiftExperimental...
Avatar
omochimetaru 8/8/2017 2:56 AM
お〜
Avatar
サマーインターンとはいえ、彼らが使う予定の無いもの作らせるとは思えないから、SwiftでlibSyntax使ってエディタエクステンション作れるようになる布石としか思えないですよね。 (edited)
Avatar
omochimetaru 8/8/2017 4:24 PM
[swift-evolution-announce] Swift 5: start your engines ... Now it is time to turn our attention to Swift 5.
😀 1
4:26 PM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
norio_nomura 8/8/2017 8:57 PM
requiring that all proposals have an implementation before they are officially reviewed by the Core Team まあ妥当
8:58 PM
every evolution proposal will need a working implementation, with test cases, in order to be considered for review. そのページだとこっちか。
Avatar
早速この前の range.contains(anotherRange) について書いてみました。↓みたいな感じで投げてみようかと。 [Pitch] range.contains(anotherRange) Hi, Recently I needed to implement `contains` methods to check if a range contains another range. I think those are basic operations and suitable for the standard library. Although it may seem easy to implement such `contains` methods whenever we need them, their precise specifications are too complicated to do so. e.g. let a: ClosedRange<Int> = 2...7 a.contains(3...5) // `true` a.contains(3...7) // also `true` a.contains(3..<8) // still `true` because all values contained in `3..<8` are also in `a` a.contains(3..<9) // `false` let b: ClosedRange<Float> = 2...7 b.contains(3...5) // `true` b.contains(3...7) // `true` b.contains(3..<8) // `false` because { x | 7.0 < x < 8.0 } is not contained in `a` let c: Range<Float> = 2..<7 c.contains(3...5) // `true` c.contains(3..<7) // `true` c.contains(3...7) // `false` because 7.0 is not contained in `a` My experimental implementation is here: https://github.com/koher/range-contains What are your thoughts about them?
Avatar
omochimetaru 8/9/2017 1:56 AM
よさそう
Avatar
~=対応もあったらswitchでつかえて楽しくなりそう
Avatar
omochimetaru 8/9/2017 1:58 AM
それは別の話にしておかないとそっちでけられたときにcontainsも入らなくなりそう。
Avatar
まぁそうですね
Avatar
追加要素として検討の価値はありそう。一般的な(他の言語の)パターンマッチで range の包含関係ってどう扱われるんだろう?
Avatar
これ作ってて思ったんだけど、 Conditional Conformance が導入されたら CountableXxxRangeXxxRange は統合できるのかな?
2:09 AM
ああ
2:09 AM
Conditional Conformance 関係ないか
2:09 AM
ってか、今でももしかして extension でできる??
2:10 AM
やっぱ Conditional Conformance か?
Avatar
最大値最小値はどれでも取れたと思うのでrightOpenプロパティをつければいける?
Avatar
↓みたいな extension Range: RandomAccessCollection where Bound: Comparable&_Strideable, Bound.Stride: SignedInteger { ... } (edited)
Avatar
For consistency, the name for this function would be `isSuperset(of:)`, and it would be equally interesting to have `isStrictSuperset(of:)`, `isSubset(of:)`, `isStrictSubset(of:)` and `isDisjoint(with:)`--all currently available for types that conform to `SetAlgebra`. というフィードバックがあって、さらに It’s a shame that Range can’t be made to conform to SetAlgebra as it lacks the required initializers. Is there anything that can be done about this? Actually, it makes me wonder whether those initializers should even be a part of SetAlgebra — why must something implementing SetAlgebra be able to be initialized as empty or from a finite sequence? という意見が。確かになんで↓等のイニシャライザを持ってるんだろう? SetAlgebra が集合のオペレーションを規定するものであれば、イニシャライザは余計な気が。 https://developer.apple.com/documentation/swift/setalgebra/2908139-init (edited)
Avatar
omochimetaru 8/9/2017 5:35 AM
単純なコレクションとしての集合しか想定していなかったのでは?
5:36 AM
Required. Default implementation provided.
5:36 AM
あれ、デフォルト実装がある??
5:37 AM
空のinitも困った存在ですね、空を許す型しかこれにconformできないのか
Avatar
うん。
Avatar
omochimetaru 8/9/2017 5:38 AM
まあRangeならたまたま空が表現できるけど。
Avatar
ClosedRange はできない。
Avatar
omochimetaru 8/9/2017 5:38 AM
あれ、マイナスにできないんですっけ?
5:38 AM
1...0
5:38 AM
みたいにして。
Avatar
できないはず。
Avatar
omochimetaru 8/9/2017 5:38 AM
fatal error: Can't form Range with upperBound < lowerBound
5:38 AM
本当だ、実行時エラーになった。
Avatar
@koher 上のサンプルですけど
5:41 AM
let a: ClosedRange = 0...1 a.contains(0..<0) // true a.contains(1..<1) // true a.contains(2..<2) // true <- ?
5:42 AM
そもそも空のcontainはどうするべきなのか
Avatar
omochimetaru 8/9/2017 5:42 AM
Rangeは空にならないでしょう
5:43 AM
長さが0なだけでlowerboundの点を含む
5:43 AM
なんていえばいいんだ?
Avatar
その場合は true
5:43 AM
空集合だから
Avatar
omochimetaru 8/9/2017 5:43 AM
[1, 2) は 大きさはもたないけど1の点は含む
Avatar
↓の挙動とも一貫性がある。 1> let a = [0, 1] a: [Int] = 2 values { [0] = 0 [1] = 1 } 2> a[2..<2] $R0: ArraySlice<Int> = 0 values
Avatar
omochimetaru 8/9/2017 5:44 AM
え、 2..<2 は空集合じゃなくて
5:44 AM
2の点だけを含むんじゃないんですか?
Avatar
a.contains(3..<3) // false
Avatar
おー、実装ミスだ
Avatar
omochimetaru 8/9/2017 5:44 AM
2..<3 のときは、2の点と、3より小さな実数「すべて」だけど
5:44 AM
2..<2 のときは 「2」は含みますよね。
Avatar
いまのロジックが漏れてるだけですが
Avatar
omochimetaru 8/9/2017 5:44 AM
集合として。
Avatar
2...22 を含むけど
5:44 AM
2..<22 を含まない (edited)
Avatar
omochimetaru 8/9/2017 5:44 AM
ええ??
Avatar
(2..<2).map(print)したら何も出なくないですか?
Avatar
omochimetaru 8/9/2017 5:45 AM
それは別に関係ないでしょ
5:45 AM
.map の振る舞いの話だから
Avatar
ん?
Avatar
いや、 2 を含むなら表示されるはずでは?
Avatar
そうですよね?
Avatar
omochimetaru 8/9/2017 5:45 AM
あーそういうもんなのか?
Avatar
(2..<2).forEach { print($0) }
Avatar
(2...2).map(print)なら当然2がでるので
Avatar
↑は何も表示しない。
Avatar
mapは確かにおかしかった
Avatar
1> (2..<2).count $R1: Int.Stride = 0
5:46 AM
↑からも空集合とわかる
Avatar
omochimetaru 8/9/2017 5:55 AM
countってプロパティ名わかりにくいですよね
5:55 AM
Int型のRangeならそれでいいけど
Avatar
Countable じゃないと count ないよ
Avatar
そもcountはCountableRangeにしか生えていないのでは?
Avatar
omochimetaru 8/9/2017 5:56 AM
実数の [1.0 , 2.0) を考えたときには個数は無限にあるし。
5:56 AM
あ、そうなのか
5:56 AM
あーでもそうか、 (2..<2) は [2] じゃなきゃおかしいな。
Avatar
2..<2[] では?
Avatar
omochimetaru 8/9/2017 5:58 AM
よくわからなくなってきた
5:59 AM
Range は Half Open だから lower を含んで upper を含まないけど
6:00 AM
( x | l <= x , x < u ) と考えると、 2..<2 は 空集合でよくて
6:00 AM
「2 だけを含む」集合が、 Range ではそもそも表現されない?
Avatar
それは2...2
Avatar
omochimetaru 8/9/2017 6:00 AM
Countable Range だと、 2...2 として表現できる 2 <= x, x <= 2 で。
Avatar
lower を含んで upper を含まないというのがそもそも矛盾を内包していて
Avatar
2..<2 は数学的に書くと [2, 2) となって意味不明になっちゃうのでは? (edited)
Avatar
2..<2ってあり得る?
Avatar
Swift 的にはありえます。
Avatar
[2, 2) ですよね
Avatar
あ、そうです。
6:01 AM
修正しました。
Avatar
omochimetaru 8/9/2017 6:01 AM
数学的には [2, 2) == () ? (edited)
Avatar
な気がする。
Avatar
数学で [a, b) という表記が b <= a に対して許されているのかがわからない。
Avatar
のはず
6:02 AM
b<aについてはswiftも許してないですね
Avatar
2か2より大きくて、2より小さい ってことですよね
Avatar
omochimetaru 8/9/2017 6:02 AM
(forall x | 2 <= x, x < 2 ) (edited)
Avatar
↑それは余裕で空集合かと。
Avatar
omochimetaru 8/9/2017 6:03 AM
数学の [a, b) 表記は ↑のエイリアスかと思ってた
Avatar
数学の場合は空集合が必ず一意だから[a, a)という記法を用意する必要がないとか? (edited)
Avatar
まあ、記法については厳密には決まってないのかも?コンパイルするわけじゃないし。
Avatar
omochimetaru 8/9/2017 6:05 AM
let a: ClosedRange = 0...1 a.contains(2..<2) // true <- ? 結局これは正しそう。 (edited)
6:05 AM
[0, 1] は [] のスーパーセットだから
Avatar
集合の定義的にもそうですね
6:06 AM
最初にa.contains(3..<3) // falseを指摘すればよかった (edited)
Avatar
omochimetaru 8/9/2017 6:07 AM
今 3..<3 は false になってるのか
Avatar
空集合のみ特別にロジックが要るはずですね
Avatar
omochimetaru 8/9/2017 6:08 AM
ああ、範囲の判定で書いてるから
6:08 AM
空のときだけその書き方でうまくいかなかったのか。
Avatar
ただし、a = b のとき、(a, a), [a, a), (a, a] は何れも空集合を表し、[a, a] は一点集合 {a} を表す。また a > b のときは、四種類ともふつうは空集合を表すものと約束する。
http://bit.ly/2vkBLBP
(edited)
👍 2
6:09 AM
数学でも Swift と同じだ。 (edited)
Avatar
omochimetaru 8/9/2017 6:10 AM
あ、さっきの内包表記に対して := とされているんですね
🙂 1
Avatar
リンクがうまく貼られなかったので修正
6:11 AM
ちゃんと集合の表記のエイリアスになってるっぽい
6:12 AM
ISO 31-11 で定められてるらしいw
Avatar
(isEmptyしたほうが良いと思った)
7:17 AM
数学でも Swift と同じだ。
a > bはクラッシュするので同じとは言えないような気もしますね
7:21 AM
レビューに書いとこう
Avatar
あれ? Range<Int> でも isEmpty 使えるんだね。 Countable だけかと思ってた。
7:33 AM
count もできる。
7:34 AM
これは Conditional Conformance が入ったら Countable を非 Countable に統合する布石?
Avatar
empty判定はupperBoundとlowerBoundだけでできますからね
Avatar
ん? Range<Float> でも isEmpty できるのか。
Avatar
omochimetaru 8/9/2017 7:35 AM
1...0 が禁止されているのに
Avatar
ん?countもできるんですか?
Avatar
omochimetaru 8/9/2017 7:35 AM
CountableRangeにisEmptyメソッドがあるんですか?
Avatar
/// A Boolean value indicating whether the range contains no elements. /// /// Because a closed range cannot represent an empty range, this property is /// always `false`. public var isEmpty: Bool { get }
Avatar
omochimetaru 8/9/2017 7:35 AM
/// always false.
7:36 AM
お、おう
Avatar
Range<Int>count もできる。
Avatar
ほんとだ
7:36 AM
collectionと無関係につけてるだけか
7:37 AM
/// Unfortunately, we can't forward the full collection API, so we are /// forwarding a few select APIs.
Avatar
@mono さんが前に Range についてまとめてたけど、 Range<Int>count できたり、 Conditional Conformance が入ったら Countable と統合できるのかとか、何か知らないかな?👀
🤔 1
7:39 AM
we can't forward the full collection API
これって Conditional Conformance のことを言ってるのか、それとも実現不可能な API があるってことを言ってるのか。後者なら Conditional Conformance が入っても統合できない?
Avatar
few selected APIでcount以外無い気がするのでそれならconditional conformanceでいけそう
7:40 AM
いやちがうのか
7:41 AM
精査すべきはcollection側か
7:44 AM
@t.ae が Reviewer になってるけど、権限のないリポジトリに自分で自分を Reviewer に指定するとかできるんだっけ?
Avatar
レビューしたら勝手につくみたいですね
7:45 AM
なんか×ついたままだし改めてapproveしないとなのか
Avatar
あ、 approve されたw
Avatar
SetAlgebra には insert, update, remove もあるのか。
Avatar
SetAlgebraRange に適用するのは全然だめだ
8:02 AM
union とかも Self を返すので無理だ。
Avatar
そもそもRangeって暗黙に順序が規定されてるようなものなのでSetAlgebraには向かない気がしますね
8:04 AM
Range<Int>とかがCollectionに従うのはいけそう
Avatar
順序は規定されてないのでは? Countable なやつだけで。
Avatar
ああRangeってSequenceにも従ってなかったのか
Avatar
omochimetaru 8/9/2017 8:05 AM
え、そうなの、
Avatar
Countableしかまともに使ってなかったのでそこが抜けてました。
Avatar
omochimetaru 8/9/2017 8:05 AM
Sequenceだから for in できるのかと思ってた
Avatar
0..<1 とかででできるのはCountableRangeなので
Avatar
omochimetaru 8/9/2017 8:06 AM
あーなるほど
Avatar
let a: Range<Int> = 0..<1 for i in a { print(i) } Playground execution failed: error: MyPlayground.playground:76:10: error: type 'Range<Int>' does not conform to protocol 'Sequence' for i in a { ^
Avatar
omochimetaru 8/9/2017 8:06 AM
だいたいよく使ってるのは実はCountableRangeだったのか
Avatar
Rangeを何に使うのかよく分からない
Avatar
omochimetaru 8/9/2017 8:07 AM
辞書順文字列の範囲とか。
8:08 AM
辞書順文字列はある2つの文字列の間に含まれる文字列が無限にあるから
8:08 AM
countableにならないけど
8:08 AM
ある文字列がその範囲にあるかどうか判定することはできる
Avatar
なるほど。
Avatar
omochimetaru 8/9/2017 8:09 AM
っていうかそれこそ FloatのRangeもuncountableなのかな?
8:09 AM
実際にはビット表現の都合でcountableだけど。
Avatar
Floatを有限集合と見なすかどうかで変わってきそう
Avatar
omochimetaru 8/9/2017 8:09 AM
ですね
Avatar
実際CountableRange<Float>はつくれないですし
Avatar
omochimetaru 8/9/2017 8:11 AM
Bound : _Strideable
8:11 AM
これで決まってるのか
Avatar
さらにBound.Stride : SignedIntegerがあってここは超えられないはず
Avatar
omochimetaru 8/9/2017 8:11 AM
ほんとだw
8:12 AM
それかなりきつい制約な気がする
8:12 AM
SignedIntegerではないがcountableなものってある気がする
Avatar
うん、 "a"..."z" とかね。
Avatar
omochimetaru 8/9/2017 8:12 AM
UInt32とか
Avatar
norio_nomura 8/9/2017 8:12 AM
@koher コメントが全部 "contained in a" になってる。メールやtestExample()で。 _ = b.contains(3..<8) // `false` because { x | 7.0 < x < 8.0 } is not contained in `a` … _ = c.contains(3...7) // `false` because 7.0 is not contained in `a` (edited)
😇 1
Avatar
おお、ありがとうございます。
Avatar
omochimetaru 8/9/2017 8:13 AM
@t.ae FloatはStridableだった。
Avatar
そこまではSignedNumberだからいけるんですね
Avatar
omochimetaru 8/9/2017 8:15 AM
https://developer.apple.com/documentation/swift/float ここだと直接conformanceある
Avatar
まあ、いま何らかの都合で SignedInteger になってても、緩める方向には互換性を保ってできそう。
Avatar
omochimetaru 8/9/2017 8:16 AM
そうですね
Avatar
0.0..<1.0とかストライドいくつなのか不明ですしStrideToでやれって話になりそうな
8:17 AM
Intは最小単位があるからいいんですけど
Avatar
omochimetaru 8/9/2017 8:18 AM
func advanced(by: Self.Stride) Returns a Self x such that self.distance(to: x) approximates n. Required. Default implementation provided.
8:18 AM
Stridableのadvancedでいくつすすむかは型によるのかな
8:18 AM
いや、byか
8:19 AM
気になってきた
8:20 AM
BinaryIntegerに T: BinaryIntegerを取るコンストラクタがあるから
8:20 AM
CountableRangeはBound: SignedIntegerを規定しているので
8:20 AM
普通に Bound(1) とかやってそう。
Avatar
Strideable って前は一つずつ進められる型だと思ってたんだけど、どうも一次元的に並べられる程度の意味っぽいよね。
8:26 AM
Comparable と表現している概念に違いはあるのかな??
Avatar
omochimetaru 8/9/2017 8:27 AM
Comparableは比較可能性だから
8:27 AM
間の刻みは関係ないんじゃないですかね
Avatar
Strideable も刻みの話をしてなくない?
Avatar
omochimetaru 8/9/2017 8:27 AM
さっきの辞書順文字列とか
Avatar
omochimetaru 8/9/2017 8:27 AM
「一つ次」が何かも定まらないです
8:27 AM
さだまるか?
8:28 AM
Stridableは Stride分すすめる/もどれる だから
Avatar
1つではなく、任意の距離が存在する、という話に見える
Avatar
omochimetaru 8/9/2017 8:29 AM
Conforming types are notionally continuous, one-dimensional values that can be offset and measured.
8:29 AM
offsetが進んだり戻ったりでmeasuredは距離が測れるってことかな
Avatar
さっきの文字列はComparableですけどStrideableではありえないですよね?
Avatar
omochimetaru 8/9/2017 8:29 AM
Strideableではある気がしてきて考え中。
8:30 AM
xxxxxx の次は必ず xxxxxa なんじゃないかな
Avatar
でもさ、 Strideable.Stride を二点で表せるくない?
Avatar
omochimetaru 8/9/2017 8:30 AM
無限にaが伸びていくので b が無限に遠くにあるけど。 (edited)
Avatar
文字列はどうだろう
Avatar
"aaa""xxxxx" の距離は ("aaa", "xxxxx") で表せないかな?
Avatar
文字ならStrideableとできる気はするけど
8:31 AM
aaaとxxxで距離が無限になるから厳しそう
Avatar
あー
8:31 AM
+= Stride とかができなきゃいけないのか。
Avatar
omochimetaru 8/9/2017 8:31 AM
たしかに。 "bbb" にたいして 距離 ("aaa", "xxxxx") を足す、って
8:31 AM
結果がわからないですね
8:32 AM
"aaa" に 距離 ("aaa", "xxxxx") をたしたら "xxxxx" になることだけは言えるけど。
Avatar
そうすると、 Strideable で表現している概念と Comparable の差分は、 2 点間の距離を規定することができる(その距離による増減は任意の点に対して適用可能である)ってことなのかな?
Avatar
omochimetaru 8/9/2017 8:34 AM
だと思います
8:34 AM
( Stridable なら Comparable ではありそう、と思ったら、そう書いてあった。 (edited)
Avatar
距離はStride型なので、Selfである必要は必ずしも無い
Avatar
omochimetaru 8/9/2017 8:36 AM
TimePoint型のStrideはTimeInterval型、とかできそう。
Avatar
数が Strideable を満たすのは当然なんだけど、他にどういう例があるんだろう?
Avatar
omochimetaru 8/9/2017 8:37 AM
@taketo1024 さんってここには居ないんだっけ・・・ (edited)
Avatar
Character は厳しいけど(複数コードポイントを含むから)
Avatar
omochimetaru 8/9/2017 8:37 AM
居ない
Avatar
アルファベット型とか作れば Strideable なのかな?
Avatar
omochimetaru 8/9/2017 8:37 AM
その他の Strideable なものですか?
Avatar
charがstrideableじゃないですか?
8:38 AM
というか順序集合は実質整数みたいなものだし考えても意味無さそう
Avatar
omochimetaru 8/9/2017 8:38 AM
アルファベットみたいに、 実質的に Int にエンコードできる型 は全部そうですよね (edited)
8:38 AM
そうじゃない系があるかなあ
Avatar
@t.ae Swift の Character は書記素クラスタなので複数のコードポイントを含むので Strideable にできないよ。
Avatar
いやcのcharです
Avatar
omochimetaru 8/9/2017 8:39 AM
UnicodeScalar が Strideableかな
Avatar
整数や数値にエンコードできるものって言ったら、実質的に Strideable == Stride になっちゃっておもしろくなさそう。
8:40 AM
たしかに、数学の世界でもっと特殊なやつがありそうな・・・ < @taketo1024 さんってここには居ないんだっけ・・・
Avatar
omochimetaru - Today at 5:11 PM ほんとだw それかなりきつい制約な気がする SignedIntegerではないがcountableなものってある気がする koher - Today at 5:12 PM うん、 "a"..."z" とかね。 omochimetaru - Today at 5:12 PM UInt32とか ↑だけど、 StrideInt ならいいだけだから問題なさそう。
Avatar
omochimetaru 8/9/2017 8:53 AM
public struct CountableRange<Bound> : RandomAccessCollection where Bound : Comparable, Bound : _Strideable, Bound.Stride : SignedInteger {
Avatar
1> let a: UInt32 = 1 a: UInt32 = 1 2> a.advanced(by: 1) $R0: UInt32 = 2 3> UInt32.Stride.self $R1: UInt32.Stride.Type = Int
Avatar
omochimetaru 8/9/2017 8:54 AM
Boundの条件じゃなくて Bound.Strideの条件か。
Avatar
omochimetaru 8/9/2017 4:07 PM
struct NS { @available(*, unavailable) init() {} static func a() -> Int { return 99 } } NS.a() こうやってイニシャライザを潰せばネームスペース代わりのstructを値として使うことを防げると気がついた (edited)
Avatar
@omochimetaru 前にそれ、 @rintaro がcase無しenumが良いよって言ってなかったっけ
Avatar
あ〜、あった
Avatar
omochimetaru 8/10/2017 3:54 AM
switch-caseによる let as は as? ができるときと違って、評価対象の式とcaseの型に親子関係が無いといけないのと、Arrayにcovarianceが無いことが組み合わさって、以下のような挙動になっているけど納得がいかない。 class Animal {} class Cat : Animal {} var animal = Animal() var cat: Cat? = animal as? Cat // OK switch animal { case let animal as Cat: // OK print(animal) default: break } var animalArray = [Animal]() var catArray: [Cat]? = animalArray as? [Cat] // OK switch animalArray { case let animalArray as [Cat]: // Compile error !!! print(animalArray) break default: break }
Avatar
そもArrayのasは厳密にはArrayに対するcastじゃない気がする
3:58 AM
ArrayとOptionalは特別扱いの塊できもい
Avatar
omochimetaru 8/10/2017 3:59 AM
特別扱いがあることはまあいいとしても、その特別扱いが as? のときと switch case let as のときと、両方で同じように発動しないと変じゃない? (edited)
Avatar
実装漏れてるのかなとは思うけど、特別扱いじゃなくて言語仕様として確立して欲しいな
Avatar
omochimetaru 8/10/2017 4:06 AM
var animalArray: [Animal] = Array<Cat>([Cat(), Cat()]) print(animalArray) // [__lldb_expr_132.Cat, __lldb_expr_132.Cat] print(type(of: animalArray)) // Array<Animal> var catArray: [Cat]? = animalArray as? [Cat] print(catArray) // Optional([__lldb_expr_128.Cat, __lldb_expr_128.Cat])
4:06 AM
これって全要素の実行時型チェックしてるよね・・・
Avatar
norio_nomura 8/10/2017 4:28 AM
switch animalArray as Any { case let catArray as [Cat]: これだと通る…
Avatar
omochimetaru 8/10/2017 4:36 AM
class Animal {} class Cat : Animal {} var animalArray: [Animal] = Array<Cat>([Cat(), Cat()]) switch animalArray as Any { case let catArray as [Cat]: print(catArray) break default: print("default") break } 本当だ、いけますね (edited)
4:36 AM
class Animal {} class Cat : Animal {} class Dog : Animal {} var animalArray: [Animal] = Array<Cat>([Cat(), Cat()]) animalArray.append(Dog()) switch animalArray as Any { case let catArray as [Cat]: print(catArray) break default: print("default") break } こう書き換えたら default って出力に変わった。やっぱり全部見ている。
Avatar
var animalArray = [Animal]() switch animalArray { case is [Cat]: // Compile error !!! print(animalArray) break default: break } のエラーがいかれてる。
Avatar
omochimetaru 8/10/2017 4:49 AM
error: TempGround.playground:10:22: error: downcast pattern value of type '[Cat]' cannot be used case let animalArray as [Cat]: // Compile error !!!
4:50 AM
このエラーメッセージから逆に推測すると、switch + is の時はダウンキャストの形じゃないといけないのだと思いました。 [Animal] と [Cat] はお互いにどちらも親子関係に無いからこのエラーがでる
4:51 AM
あ、そうか、 as Any つけておくと、 Any と [Cat] は親子関係があるからダウンキャストパターンに合致する・・・?
Avatar
そもそも var catArray: [Cat]? = animalArray as? [Cat] ができてしまうことが変な気が。
5:44 AM
これって var catArray: [Cat]? = sequence(animalArray.map { $0 as? Cat }) と等価なのか。
Avatar
omochimetaru 8/10/2017 5:49 AM
Dogが混ざっていたときの挙動が違うのでは?
5:49 AM
sequenceはSomeのTだけあつめる関数ですよね
5:49 AM
as? は Dogが混ざっていると変換自体が失敗になった
Avatar
そもそも後者は型が違う
5:49 AM
[Cat?]になってる
Avatar
omochimetaru 8/10/2017 5:49 AM
いや、sequenceで [Cat?] -> [Cat]? になる
Avatar
あ、sequenceで潰してるのか
Avatar
sequence は一つでも nil なら全体が nil になるはず。
Avatar
omochimetaru 8/10/2017 5:50 AM
ただ潰し方が as? とは違うのでは?ってこと
5:50 AM
あれ、そうだっけ
Avatar
@omochimetaru の言ってるのは flatMap では?
Avatar
omochimetaru 8/10/2017 5:50 AM
sequenceとflatMapって同じじゃなかったですっけ、OptionalのflatMapが無いときにsequenceを使えば、みたいな話があった気が
Avatar
その場合戻り値の型は [Cat] になる。
5:51 AM
sequence は標準ライブラリにないのでそんな話にはならない気が。
Avatar
omochimetaru 8/10/2017 5:52 AM
いまのOptionalを潰せるflatMapがArrayにSwfift2.3?ぐらいで追加される前に
5:52 AM
sequence の話をしてた
5:52 AM
対象が Maybe モナドの場合、次のような結果となりわかりやすい。失敗するかもしれない文脈 を除いた値をリストにしている。 sequence [Just 5, Just 100] -- Just [5,100] sequence [Just 5, Nothing, Just 100] -- Nothing ( Nothing から値を取ろうとして fail が呼ばれる )
5:52 AM
リストに sequence を適用してみた結果に混乱したので整理しておく。 sequence [[1], [2], [3]] -- [[1,2,3]] はて、果たして、sequence 関数は何をやっ...
5:53 AM
ほんとだ
Avatar
map して sequencerethrows に対応していて
5:56 AM
func cast<T, U: T>(_ x: T, _ type: U.Type) throws -> U { ... } があれば var catArray: [Cat]? = try? animalArray.map { try cast($0, Cat.self) } とできる。
Avatar
omochimetaru 8/10/2017 5:56 AM
なるほど
Avatar
モナドパズルを解かなくていい。
Avatar
covariance周りのproposalとか上がってないのだろうか
Avatar
前に @rintaro さんが言ってた、 struct でも covariant にできないケースとかありましたよね?
7:01 AM
値型だと参照型と違って mutating func の引数に型パラメータを使っても covariant にできる場合もあるし( Array とか)
7:02 AM
どういう条件になるんですっけ?前に話したような気も・・・。
Avatar
"Farm が struct だった場合に" で過去ログ検索して出てくるあたりの話かな?
👍 1
Avatar
https://github.com/apple/swift/pull/11441 case let catArray as [Cat]: の件、 issue 出しておいたら、とりあえず未サポートってことになりましたw
For switch statements like the following class Animal {} class Cat : Animal {} class Dog : Animal {} func check(_ arry: [Animal]) { switch arry { case is [Cat]: () case let dogs as [Dog]...
🙂 1
Avatar
omochimetaru 8/15/2017 3:44 AM
HogehogeImporterにimportメソッドを作りたいけど予約語なので `func import()` している (edited)
3:45 AM
(バッククォートがクォートできねえ
Avatar
`func import()`
Avatar
omochimetaru 8/15/2017 3:45 AM
!
Avatar
``func `import`()``
Avatar
omochimetaru 8/15/2017 3:46 AM
お〜〜〜できた
Avatar
omochimetaru 8/15/2017 5:38 AM
class Animal {} class Cat : Animal {} class Dog : Animal {} let animals: [Animal] = [Cat(), Cat(), Dog()] print(Set(animals.map { type(of: $0) }))
5:38 AM
このプログラムコンパイルするとコンパイラがセグフォになるの俺だけ?
Avatar
Animal.TypeがHashableでないからでは?
Avatar
omochimetaru 8/15/2017 5:40 AM
コンパイルエラーじゃなくてコンパイラが吹っ飛ぶ。
Avatar
test.swift:6:7: error: cannot invoke initializer for type 'Set<_>' with an argument list of type '([Animal.Type])' print(Set(animals.map { type(of: $0) })) ^ test.swift:6:7: note: expected an argument list of type '(Source)' print(Set(animals.map { type(of: $0) })) ^
Avatar
と思ったけどセグフォはおかしい気が。
Avatar
クラッシュはしないです。
Avatar
omochimetaru 8/15/2017 5:41 AM
ふむ
5:41 AM
$ swift -v Apple Swift version 4.0 (swiftlang-900.0.59 clang-900.0.34.2)
Avatar
beta 5 でデグレ? Apple Swift version 4.0 (swiftlang-900.0.54.11 clang-900.0.31)
Avatar
omochimetaru 8/15/2017 5:44 AM
An interactive website that lets you write, execute, and share Swift code in a server environment – on top of Linux!
5:44 AM
Dev. 4.0 (Aug 4, 2017) にしたら、クラッシュした。
5:45 AM
それはそうと、 uniq したいだけのときってどうするのがいいんですかね
5:45 AM
Setにいれるのだとこの通りHashableじゃない場合にダメだ。
Avatar
ObjectIdentifierって
5:46 AM
型を引数にできなかったっけ
Avatar
omochimetaru 8/15/2017 5:46 AM
それはポインタライクなやつでは?
5:46 AM
今は配列の中に入ってるインスタンスの型をみたいんだよね
5:46 AM
まあ、 typeName: String を生やしてあるから手元の問題は解決してるんだけど・・・ (edited)
Avatar
Set(animals.map { ObjectIdentifier(type(of: $0)) }) は通るけど、元に戻せないから微妙。
Avatar
記憶が正しければ、class型の値と、任意の型はObjectIdentifierでハッシュ化できる
Avatar
omochimetaru 8/15/2017 5:48 AM
type metadata って
5:49 AM
同じ型に対して一つのインスタンスしか存在しないことが
5:49 AM
保証されてる?
Avatar
A unique identifier for a class instance or metatype. だから.Typeならいける
5:49 AM
のでは?
Avatar
omochimetaru 8/15/2017 5:49 AM
なるほど instance or metatype ってかいてあるし、metatypeはそういうもんなのか
Avatar
同じ型に対して一つのインスタンスしか存在しないことが 保証されてる?
その認識です。
Avatar
omochimetaru 8/15/2017 5:50 AM
じゃあとりあえず type(of: ) を uniq するなら、 ObjectIdentifierをkeyにしたdictにするのがよさそうか。
Avatar
最近RxSwiftのDelegateProxyがSwift4で死んだのを復活させるのにObjectIdentifierを型のハッシュ化目的で使ったから
5:51 AM
まさに、という感じだった
Avatar
omochimetaru 8/15/2017 5:54 AM
let types: [Animal.Type] = [Cat.self, Cat.self, Dog.self] print(types.reduce(into: [:]) { (d, x) in d[ObjectIdentifier(x)] = x })
5:55 AM
なるほど > ObjectIdentifierを型のハッシュ化目的で使った
5:55 AM
↑できた。 ありがとうございます。
Avatar
omochimetaru 8/15/2017 8:16 AM
デバッグ実行時にArrayを使うと、Time Profilerで調べるとストレージのヒープアロケート/デアロケートが結構重いので
8:17 AM
スタックアロケートなAPIや型が使いたいんだけど、Swiftに無いですよねえ
8:17 AM
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170417/035830.html [swift-evolution] [Pitch] Swift needs fixed-size array こんなスレもあった。
Avatar
@omochimetaru Swift は最適化なしだと色々と重いから、最適化した状態で問題になるかが重要なんじゃないかな?
Avatar
omochimetaru 8/15/2017 8:19 AM
ところが Swift Compiler と Optimizationが無効だと(デバッグビルドでもデフォルト有効なんですけど)
8:19 AM
変数の値とかもデバッガから見れないので
8:20 AM
デバッガが使えるけどそこそこの速度で動くって状態にしないと
8:20 AM
快適に作業できない。。
8:21 AM
Apple LLVM 9.0 - Code Generation / Optimization Level は、 デフォルトがDebugで -Ononeなんですけど
8:21 AM
Swift Compiler - Code Generation / Optimization Level は、デフォルトで Debug で -O なんですよね。
8:21 AM
あ、フレームワークターゲットの場合ですけど。
Avatar
@omochimetaru % for i in range(17): public struct Array${i}<Element> { % for j in range(i): var element${j}: Element % end public init( % for j in range(i): % if j == i - 1: _ element${j}: Element % else: _ element${j}: Element, % end % end ) { % for j in range(i): self.element${j} = element${j} % end } public subscript(index: Int) -> Element { get { switch index { % for j in range(i): case ${j}: return element${j} % end default: preconditionFailure("Out of bounds: \(index)") } } set { switch index { % for j in range(i): case ${j}: element${j} = newValue % end default: preconditionFailure("Out of bounds: \(index)") } } } public var count: Int { return ${i} } } % end
Avatar
omochimetaru 8/15/2017 8:40 AM
@koher OpenGLに渡すんですけど、
8:41 AM
Swiftのstored property は 、フィールドレイアウトが上から下に並ぶ保証が無いので
8:41 AM
それは使えないんですよ。
Avatar
stored property をタプルにするとか
Avatar
omochimetaru 8/15/2017 8:41 AM
タプルでも同じじゃないですかね
8:42 AM
stored property の並びがどうなるか保証は無いよって話は Ownership Manifesto に出てきた。
Avatar
じゃあ、↑のように定義した上で selfUnsafeMutablePointer<Element> として使うという黒魔術は?w
Avatar
omochimetaru 8/15/2017 8:43 AM
え、っと、なので、それが、レイアウト保証がないから、
8:43 AM
0バイト目から4バイトずつfloatが並ぶ保証がないんです。
Avatar
レイアウトの保証がなくても Element × N 個以上の領域が確保されているのは保証されるのでは?
Avatar
omochimetaru 8/15/2017 8:44 AM
あー、フィールドを気にせず使うという意味か。
Avatar
self をポインタ化すればレイアウト関係なく頭からアクセスできそうだけど、最適化の関係とかでぶっ壊れそう。
Avatar
omochimetaru 8/15/2017 8:44 AM
それはありですね、 MemoryLayout<Float>.alignment と MemoryLayout<Float>.stride も考慮して
8:44 AM
アドレスをオフセットする必要はあるけど
Avatar
ちゃんと rebound すれば問題ないのかな?
Avatar
omochimetaru 8/15/2017 8:45 AM
UInt8をフィールドにひたすら並べたstructさえあれば、それ自体はたしかにスタック上のメモリチャンクとして使えますねw
Avatar
黒魔術っぽいけどw
Avatar
omochimetaru 8/15/2017 9:00 AM
typedef struct FixedFloatArray16 { float elements[16]; } FixedFloatArray16; float * FixedFloatArray16GetElementsPointer(FixedFloatArray16 * array);
9:01 AM
// Matrix4x4 public func withUnsafePointer<R>(_ f: (UnsafePointer<Float>) throws -> R) rethrows -> R { var array = FixedFloatArray16() array.elements.0 = e00 array.elements.1 = e01 array.elements.2 = e02 array.elements.3 = e03 array.elements.4 = e10 array.elements.5 = e11 array.elements.6 = e12 array.elements.7 = e13 array.elements.8 = e20 array.elements.9 = e21 array.elements.10 = e22 array.elements.11 = e23 array.elements.12 = e30 array.elements.13 = e31 array.elements.14 = e32 array.elements.15 = e33 return try f(FixedFloatArray16GetElementsPointer(&array)) } (edited)
9:01 AM
これでうまくいった。
9:01 AM
FPS17がFPS18になったw
Avatar
norio_nomura 8/16/2017 6:41 AM
久しぶりのスナップショット swift-4.0-DEVELOPMENT-SNAPSHOT-2017-08-15-a
Avatar
omochimetaru 8/16/2017 6:41 AM
Avatar
↓みたいな初期化orアンラップのパターンをもっと簡単に書く方法ってないでしょうか? class Foo { private var bar: Bar? func baz(qux: Qux) { let bar: Bar // bar が nil なら初期化したい if let b = self.bar { bar = b } else { bar = Bar(qux: qux) self.bar = bar } // ここで bar を使う } }
5:01 PM
↓みたいなのがあれば func unwrap<T?>(_ value: inout T?, with initialize: () throws -> T) rethrows -> T { if let v = value { return v } let v = try initialize() value = v return v } ↓にできそう。 class Foo { private var bar: Bar? func baz(qux: Qux) { let bar: Bar = unwrap(&self.bar) { Bar(qux: qux) } // ここで bar を使う } }
Avatar
omochimetaru 8/17/2017 5:01 PM
lazy varにするのは?
5:01 PM
nilに戻ることもあると違うか
Avatar
Bar のイニシャライザが qux に依存してるからできなくない? (edited)
Avatar
omochimetaru 8/17/2017 5:03 PM
引数見落としてました
Avatar
func baz(qux: Qux) { let bar = self.bar ?? { self.bar = $0; $0 }(Bar(qux: qux)) // ここで bar を使う } 微妙・・・ (edited)
Avatar
短いけど可読性がw
Avatar
しかも return 抜けてるので、そんなに短くもない
5:16 PM
let bar = self.bar ?? { self.bar = $0; return $0 }(Bar(qux: qux))
Avatar
omochimetaru 8/17/2017 5:17 PM
プロパティへの代入を二行目に毎回やるようにすれば
5:18 PM
let bar = self.bar ?? Bar(qux) self.bar = bar
Avatar
なるほど。
5:19 PM
これって、 Dictionary の新しい subscript と同じパターンな気がする。
Avatar
omochimetaru 8/17/2017 5:20 PM
func setget(x : inout T, y)->T{ x = y; return y }があれば
5:21 PM
let bar = setget(&self.bar, self.bar ?? Bar(qux))
5:21 PM
こういう時評価値付きの代入文が欲しくなりますね
Avatar
extension Optional { mutating func unwrapped(default: @autoclosure () throws -> Wrapped) rethrows -> Wrapped { if let val = self { return val } self = `default`() return self! } }
5:30 PM
Dictionary の新しい subscript と同じパターンな気がする。
Dictionary は、読むだけでは mutate しないからちょっと違う感じ
Avatar
omochimetaru 8/17/2017 5:31 PM
mutating func がselfのinoutである事を利用した別解だ
Avatar
Dictionary は、読むだけでは mutate しないからちょっと違う感じ
set の方のイメージでしたが、その後使う部分はないですね。
Avatar
omochimetaru 8/18/2017 8:22 AM

導入

Swift には struct と class があります。 struct のメソッドには func ( nonmutating func の省略表記 ) と mutating func がありますが、 cla...
👍 7
Avatar
おお、面白い
Avatar
ありがとうございます😊
Avatar
omochimetaru 8/21/2017 1:40 AM
class Cat { init() { print("Cat init(\(ObjectIdentifier(self))") } deinit { print("Cat deinit(\(ObjectIdentifier(self))") } func newCat() -> Cat { return Cat() } } func f0(_ x: Cat) { print("f0") } func main() { print("a") f0(Cat().newCat()) print("b") } main()
1:40 AM
出力 a Cat init(ObjectIdentifier(0x00007fba7251c800) Cat init(ObjectIdentifier(0x00007fba725179b0) Cat deinit(ObjectIdentifier(0x00007fba7251c800) f0 Cat deinit(ObjectIdentifier(0x00007fba725179b0) b
1:41 AM
あまり意識してなかったけど、 メソッド呼び出しされてる Cat()newCat() の呼び出し前に破棄される。
Avatar
f0 前だけど newCat 後じゃない?
Avatar
omochimetaru 8/21/2017 1:42 AM
それはそう
Avatar
それはイメージ通りな気がする。
1:44 AM
Obj-C の retain/autorelease から言うと早いけど。
Avatar
omochimetaru 8/21/2017 1:44 AM
僕は関数呼び出しが終わるまでは引数部分の評価結果は全部スタックに積まれていく気がしていた
Avatar
スタックに積まれるのは渡すものだけじゃないの?
Avatar
omochimetaru 8/21/2017 1:45 AM
結論から言うとそう
Avatar
そもそも全部乗せるためには、引数部分で評価される文について特別扱いしなきゃいけなくなるから、あんまり効率良く無いと思った
Avatar
omochimetaru 8/21/2017 1:47 AM
OwnershioManifestoで、ストレージのリファレンスを関数の返り値として返す機能についての議論があって
1:48 AM
もし、さっきの newCat() のメソッドが、 &self.age みたいに、自身の stored property への storage reference を返すような関数だったとすると
1:49 AM
この挙動によって、 レシーバの Cat() が、メソッド呼び出し直後の f1 投入前に死んでるから
1:49 AM
何らかの仕組みが必要 って話が出てきて
1:49 AM
この挙動のことちゃんと認識してなかったから何日もウーンってなってたw
Avatar
&self.ageが評価されるのはnewCat()内でinitされるときじゃないの?、
Avatar
omochimetaru 8/21/2017 1:51 AM
class Cat { func ageRef() -> inout Int { return &self.age } var age: Int = 0 } f1(Cat().ageRef())
1:51 AM
↑これがうまくいかないって話
Avatar
inout Intがリファレンスカウンティング増やさないのかそれ
1:52 AM
増やさないとダメでしょ
Avatar
omochimetaru 8/21/2017 1:52 AM
inout Int はただのポインタだから、
1:52 AM
Catのアドレスはわからないし
1:52 AM
Catのプロパティとは限らないから
1:52 AM
そんなことはできないのと
1:52 AM
Catがもしstructだったら
1:53 AM
カウンタを増やして延命という概念がそもそも使えない
1:53 AM
増やす方はできても減らす方を inout Int 型の値からは適切にできない。
1:53 AM
この例なら ageRef が self のフィールドを参照することまでわかってるから無理やりできても
Avatar
コンパイル後にinout Intを何かしらの型にラップするとか
Avatar
omochimetaru 8/21/2017 1:54 AM
Catが外部コンパイルされてたら無理だし。
1:55 AM
そうだね
1:56 AM
まあなんかいろいろ実装上の工夫が必要になるのと、参照型の導入はそもそもパフォーマンスだから
1:56 AM
trivialでない仕組みはあんま入れたくないねみたいな話もあり
1:57 AM
とりあえず関数の返り値としては参照型は返す仕様は無しって方針が書いてある
1:58 AM
「関数の返り値としては」であって
Avatar
そもそも Cat.ageをinoutな引数で受ければ同じ事起きるんじゃ
Avatar
omochimetaru 8/21/2017 1:58 AM
あ、いい指摘だね、それは
1:59 AM
テンポラリ変数での呼び出しと
1:59 AM
呼び出し後の再代入に
1:59 AM
分解される。
2:00 AM
class Cat { init() { print("Cat init(\(ObjectIdentifier(self))") } deinit { print("Cat deinit(\(ObjectIdentifier(self))") } var catProp: Cat { get { return Cat() } set { print("catProp setter: \(ObjectIdentifier(self))") } } } func f1(_ x: inout Cat) { print("f1 begin") x = Cat() print("f1 end") } func main() { print("b") f1(&Cat().catProp) print("c") } main()
2:00 AM
b Cat init(ObjectIdentifier(0x00007fd899434f90) Cat init(ObjectIdentifier(0x00007fd899424d70) f1 begin Cat init(ObjectIdentifier(0x00007fd899434d50) Cat deinit(ObjectIdentifier(0x00007fd899424d70) f1 end catProp setter: ObjectIdentifier(0x00007fd899434f90) Cat deinit(ObjectIdentifier(0x00007fd899434d50) Cat deinit(ObjectIdentifier(0x00007fd899434f90) c
2:00 AM
↑の出力で、f1の呼び出し前に破棄されるCatがなくなっていることと
2:01 AM
setterの呼び出しがf1 end の後になっていることがポイント
Avatar
俺の言いたいのはfunc f2(_ x: inout Int)に、Cat().ageをぶち込むという話なんだけど
2:01 AM
これでも同じか
Avatar
omochimetaru 8/21/2017 2:02 AM
computed property じゃなくて stored property の場合ってこと?
Avatar
んだべな
Avatar
omochimetaru 8/21/2017 2:03 AM
class Cat { init() { print("Cat init(\(ObjectIdentifier(self))") } deinit { print("Cat deinit(\(ObjectIdentifier(self))") } var catProp: Cat { get { return Cat() } set { print("catProp setter: \(ObjectIdentifier(self))") } } var age: Int = 0 } func f1(_ x: inout Cat) { print("f1 begin") x = Cat() print("f1 end") } func f2(_ x: inout Int) { print("f2") x = 33 } func main() { print("b") f2(&Cat().age) print("c") } main()
2:03 AM
b Cat init(ObjectIdentifier(0x00007fb96d095a80) f2 Cat deinit(ObjectIdentifier(0x00007fb96d095a80) c
2:03 AM
stored propertyは挙動が調べられないという問題がw
Avatar
これはなんだ、内部的には最初のCatのポインタが渡ってると言う解釈で良いのか (edited)
Avatar
omochimetaru 8/21/2017 2:05 AM
どっちなんだろう
2:05 AM
computed propertyとの一貫性で言えばテンポラリ変数で受けてから呼び出し後に代入してると思うけど
2:05 AM
stored propertyであることがわかってるからレシーバのCatを延命してる可能性もあるね
Avatar
#Cat.age!materializeForSet.1
Avatar
omochimetaru 8/21/2017 2:19 AM
やたらややこしい
2:20 AM
materializeForSetの返り値を渡してるね %8 -> %9 -> %10 -> %12 -> %15
Avatar
実際にはinstance methodが渡っているように見える
2:20 AM
あー返り値なのか
Avatar
omochimetaru 8/21/2017 2:20 AM
materializeForSetは%8でロードされて%9で呼びされてる
2:21 AM
#Cat.age!materializeForSet.1: (Cat) -> (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer) -> (Builtin.RawPointer, Builtin.RawPointer?) : _T01a3CatC3ageSifm // Cat.age.materializeForSet
2:22 AM
なんともいえん materializeForSetは、Catと、ポインタ2つを引数にとって、ポインタ2つを返す・・・
2:22 AM
引数のポインタ2つは%4と%5で確保した謎のバッファーと Int
2:23 AM
stored property のあるコードをコンパイルするとだいたい materializeForSet ってメソッドが生成されるんだけどこれ謎だ
Avatar
omochimetaru 8/21/2017 2:24 AM
SIGLENのテストコードってこんなふうになってるんだw
2:28 AM
返してるポインタの1つ目はCat.ageのフィールドのアドレスで、2つ目は関数ポインタだ
2:34 AM
Law of Exclusivity が入ってるから、
2:35 AM
stored propertyのアクセス終了通知用の関数が返ってくるのかも
2:36 AM
Catをstructにするとコンパイルエラーだわ a.swift:10:8: error: cannot pass immutable value as inout argument: function call returns immutable value f2(&Cat().age) ^~~~~~
Avatar
ほー
2:36 AM
ああ、Cat()だけだとimmutableだもんね
2:36 AM
それはそう (edited)
Avatar
omochimetaru 8/21/2017 2:44 AM
さっきのclass CatのやつはmaterializeForSetを通じてCat.ageのアドレスを取ってきて渡してた Catの生成とそのアドレスの取得はf2の呼び出し前にやって、呼び出し後にCatを破棄 (edited)
Avatar
特別扱いっぽい
Avatar
omochimetaru 8/21/2017 2:47 AM
materializeForSetはポインタ2つを引数に (フィールドのアドレス, 片付け関数) のタプルを返してたけど、 引数の方のポインタ1つめは使われてないし、2つ目は begin_unpaired_access [modify] [dynamic] 命令がSIL.rstに書いて無くて用途が謎
2:48 AM
片付け関数の中に end_unpaired_access があって、これとペアになっていて、なんかメタ情報をやり取りしてるけど謎だ
Avatar
これってコンパイラがリファクタリング機能を持って、コマンド経由で実行できるようになるってことですか?
Avatar
まだよく見てないんですが、Xcode9 のリファクタリング機能だと思います。 SourceKit に機能追加されている。
Avatar
swift-refactor っていうコマンドラインツールもありますね。
Avatar
↑がメインの機能かな?
1:32 AM
コマンドからできるようになると色々発展がありそうですね。
1:32 AM
Swift の API があればそれもよりいいですが・・。 (edited)
Avatar
Xcode 9 includes a brand new refactoring engine. It can transform code locally within a single Swift source file, or globally, such as renaming a method or property that occurs in multiple files and even different languages. The logic behind local refactorings is implemented entirely in the compiler and SourceKit, and is now open source in the swift repository. Therefore, any Swift enthusiast can contribute refactoring actions to the language. This post discusses how a simple refactoring can be implemented and surfaced in Xcode.
👀 1
Avatar
"Cursor-based Refactoring" って DB のカーソルみたいなデータ操作の話かと思ったら本当の UI のカーソルだった・・・。
Avatar
omochimetaru 8/23/2017 1:50 AM
これを使うとCot EditorにSwiftのリファクタリング機能をつけたりできるのかな。
1:51 AM
単一ファイルで完結する系の事だけ。
Avatar
それほしい。
Avatar
omochimetaru 8/23/2017 1:51 AM
Xcode9 beta5で、Xcode自体をCmd+Qで殺さないといけなくなったから
1:51 AM
作業プロジェクトとは別に、ちょっと.swift開きたいときに
1:51 AM
別のエディタを使う必要があるので
Avatar
ああ、ここに 1024jp さんいなかった・・・
Avatar
omochimetaru 8/23/2017 1:52 AM
そういうときにちょっとリファクタリングがついてるとよい
Avatar
↓社内Slackで @omochimetaru と話していたこと。
  • Swift に sealed class がほしい
  • そのまえに abstract class が必要では?
  • いや、ほしいのは sealed protocol
  • enum に(共通の) stored property を持たせられたら解決するのでは?
  • case は型じゃないからパターンマッチのときにプロパティをバラさないといけなくて辛い
  • case が型でないのが問題なのでは? ←今ココ
3:30 AM
あ、でもenumが値型だから妙なことになるのかな。
値型に継承があっても値のメモリレイアウトを変更しないなら問題ない気がする。
Avatar
omochimetaru 8/23/2017 3:31 AM
いや、そもそもSwiftのenumはassociated valueがいろいろあるからメモリレイアウトは違うんですよね。 (edited)
Avatar
前から、純粋にメソッドや computed property 足して型として区別できる struct の継承ほしいと思ってる。 (edited)
Avatar
omochimetaru 8/23/2017 3:31 AM
どれでも入れられるサイズになってる
3:31 AM
UnitTypeみたいなことですか?
Avatar
うん、どれでも入れられるという意味でメモリレイアウト
Avatar
omochimetaru 8/23/2017 3:32 AM
struct Dimension : Int
Avatar
case サブタイプのレイアウトは異なってもいいか。
Avatar
omochimetaru 8/23/2017 3:32 AM
みたいな。
Avatar
そうそう < Dimension
Avatar
omochimetaru 8/23/2017 3:32 AM
それ欲しいですよね has_aで作ったらまあメモリサイズ的には実際それにちかいけど
Avatar
struct Path: String とか。
3:33 AM
has_a だと、メンバを実装し直さないといけないのが辛い。
Avatar
omochimetaru 8/23/2017 3:33 AM
あ、なるほど
Avatar
あと、アップキャストが明示的になるのが。
Avatar
omochimetaru 8/23/2017 3:33 AM
var base: Int
3:33 AM
があれば良い気もした。
3:34 AM
明示的にはなる。
Avatar
うーん・・・
3:35 AM
話がそれた。case を型にするのはどうなんだろう?
Avatar
omochimetaru 8/23/2017 3:35 AM
なんかそれは欲しい人いっぱいいる気がするんだよな
Avatar
でもそうすると case を小文字にした弊害がw
Avatar
omochimetaru 8/23/2017 3:35 AM
@ikesyo@hiragram も会った時言ってた気がしなくもない
Avatar
型なら Optional.some じゃなくて Optional.Some であってほしい。
Avatar
omochimetaru 8/23/2017 3:36 AM
もっかい大文字に直そう 😂
😇 1
Avatar
なんだなんだ
Avatar
omochimetaru 8/23/2017 3:36 AM
@hiragram caseに個別の型ほしくない?
Avatar
ほしい。
3:36 AM
言った。
Avatar
omochimetaru 8/23/2017 3:38 AM
そうすると、小文字だと困るよね
Avatar
この流れどこから読めばいいですか
Avatar
omochimetaru 8/23/2017 3:39 AM
koher - 今日 午後12時29分
から
Avatar
caseに型をっていうのは enum Hoge { case fuga case piyo var data: ??? { ... } } ???がcaseごとに違う型返せる って認識でよかですか
Avatar
enum Foo { let a: Int let b: String case Bar case Baz(c: Float) case Qux(d: Bool, e: Double) } ↑ができて case が型になればやりたいことは大体できそう。 (edited)
Avatar
omochimetaru 8/23/2017 3:42 AM
たとえば、 case fuga のときだけ使えるメソッドを定義するとか。 (edited)
Avatar
switch foo { case let bar as Bar: ... case let baz as Baz: ... case let qux as Qux: ... } (edited)
3:43 AM
@omochimetaru extension Foo.Qux { var ee: Double { return e * e } }
Avatar
Bar Baz Quxはそれぞれcaseってことですよね?
3:44 AM
ああ、書いてあったわ
Avatar
omochimetaru 8/23/2017 3:45 AM
foo bar bazの次がquxってことを今知った
😄 1
Avatar
話題の本質と違うからここに書かなかったのにw
Avatar
↓もできるイメージ switch foo { case .Bar(let a, _): ... case .Baz(let a, _, let c): ... case .Qux(let a, _, let d, _): ... }
Avatar
omochimetaru 8/23/2017 3:47 AM
[swift-evolution] Treating an Enum's Cases as Its Subtypes
3:47 AM
おお
3:48 AM
2017年2月
Avatar
I think there are definitely places where having cases be a subtype of an enum make sense, but I don't think it makes sense for *all* cases to be subtypes. For example, with "biased" containers like Optional and Result, it makes sense for the "right" side to be a subtype and the "wrong" side to be explicitly constructed, IMO. If the types of cases overlap, it would also be *ambiguous* which case ought to be constructed when the payload is converted to the enum type—remember that enums are sums, not unions, and that's important for composability and uniform behavior with generics. I would be fine allowing enum subtyping with some opt-in attribute, e.g.: enum Optional<Wrapped> { sub case some(wrapped) case none } enum Result<Wrapped> { sub case ok(wrapped) case error(Error) // not a subtype } enum JSON { // OK for these to all be sub-cases, since they don't overlap sub case string(String), number(Double), array([JSON]), object([String: JSON]), null } enum Either<T, U> { // Error: sub cases potentially overlap sub case left(T), right(U) } -Joe
3:51 AM
なんかちょっと言ってることと違う気がする。
Avatar
omochimetaru 8/23/2017 3:52 AM
noneやerrorに型がついちゃってると困るケースがわからない
Avatar
enum E { case Foo { func fooMethod() { ... } } case Bar { func barMethod() { ... } } } みたいな proposal もあった気がするんだけどみつからない。
Avatar
ちょっとしばらく考えてたんですが
8:27 AM
RawRepresentableのRawValueにProtocolを定義できるようになれば、やりたいことは実現可能なのでは。
8:27 AM
enum E: RawRepresentable { typealias RawValue = MyProtocol case x = MyProtocolImpl1() case y = MyProtocolImpl2() } こんな感じで
Avatar
omochimetaru 8/23/2017 8:28 AM
お・・・
Avatar
それだとすべての case が同じ型になりませんか?
Avatar
ん、コンパイル時にE.xとE.yは区別ついてないとこまるのか
8:30 AM
ふーむ・・・その要求だとRawRepresentableはムリですねぇ
Avatar
omochimetaru 8/23/2017 8:31 AM
Rawvalueは全case共通か。
Avatar
そうそう、
8:31 AM
e.rawValue こいつがProtocol型になることを想定している
Avatar
理想はプロトコルじゃなくて各caseごとに任意の具体型が直接とりだせたらいいなあ
Avatar
完全にRawRepresentableの役割の外だなぁ
8:33 AM
それさ
8:33 AM
enumじゃなくてネストした型にしたほうがいいんでない?
8:33 AM
コンパイル時に網羅性もチェックしたいのか
Avatar
今はそうしてる。
8:33 AM
網羅性は一旦目をつぶっている。
Avatar
その網羅性問題のために @omochimetaru と相談して Switcher なるものを作ることにしました。
⭐ 1
Avatar
omochimetaru 8/23/2017 8:37 AM
@koher と一緒に考えたアイデアによって
8:37 AM
継承と網羅性を両立できる
8:37 AM
デザインパターンがある
Avatar
おっ
Avatar
omochimetaru 8/23/2017 8:39 AM
enum AnimalTypeSwitcher { case cat(Cat) case dog(Dog) } class Animal { var switcher: AnimalTypeSwitcher { fatalError("unimplemented") } } class Cat : Animal { var nya: Int = 3 override var switcher: AnimalTypeSwitcher { return .cat(self) } } class Dog : Animal { var wan: Float = 1.2 override var switcher: AnimalTypeSwitcher { return .dog(self) } }
Avatar
class Base { ... var switcher: Switcher { fatalError("abstract") } enum Switcher { case foo(Foo) case bar(Bar) case baz(Baz) } } class Foo: Base { ... override var switcher: Base.Switcher { return .foo(self) } } ...
8:40 AM
書くの負けた・・・w
Avatar
omochimetaru 8/23/2017 8:40 AM
Animalから型によって分岐したいときに、 switch animal.switcher って書く。
8:40 AM
Animal / Cat / Dogは普通の継承関係だからオーバライドとかも自由に使えるよ。
Avatar
本当は↑の Baseprotocol にしたいけどそうすると nested type がつくれないから Switcher を外出ししないといけない。
Avatar
omochimetaru 8/23/2017 8:41 AM
@koher Switcherをnested typeにするのか。そのほうがいいっすね。
Avatar
@omochimetaru みたいに外出しするなら protocol で OK だと思う。
8:42 AM
sealed class 的な網羅性を保証するためのワークアラウンドですね。
8:42 AM
まさに今日これに助けられて新しい型を追加したときに網羅チェックで分岐の漏れを見つけられた。
Avatar
やりたいことは実現できてよさげですが、いっぱい書かないといけないですねw
Avatar
omochimetaru 8/23/2017 8:43 AM
うん。なので、 enum の case に型がついてればよかったのにね、って主張になる。
Avatar
Switcher.swift.gyb
8:44 AM
gyb でできるかな?
Avatar
これのポイントは
8:44 AM
えーっと
Avatar
omochimetaru 8/23/2017 8:44 AM
たしかに、var switcher の実装は Animal側によせちゃってもいいので
8:44 AM
ありかも。
Avatar
継承しているclass側に直に書かなくてもいいので
Avatar
omochimetaru 8/23/2017 8:44 AM
var switcher を extentionでかいてもいいから
8:44 AM
gybでファイル分割してても問題ないね
Avatar
extension Base { enum Switcher { ... } }
8:44 AM
そり
8:45 AM
引数にBase型と継承型を列挙したら吐き出すことはできるはずだ
Avatar
omochimetaru 8/23/2017 8:46 AM
おもしろい
Avatar
Visitor パターンの switch 版っぽい味わい。
Avatar
コード生成コストもO(n)で問題はないぞ
8:50 AM
ああああああああああああ
8:50 AM
ダメだ
8:50 AM
Swift4からextensionに書いたメソッドをoverride出来なくなりました
8:50 AM
ちーん
Avatar
extensionに書いたメソッドをoverrideって具体的にどういうことだっけ
Avatar
extension UIViewController { var myNantokaField: Int { return -1 } } extension MyViewController { override var myNantokaField: Int { return 1 } } // Clompile Error.
8:52 AM
これです
Avatar
それって動的ディスパッチできないんじゃなかったですっけ?
Avatar
あー。親のextensionをってことね
Avatar
RxSwiftで
8:54 AM
死んだのを思い出した
Avatar
let vc1: MyViewController = ... let vc2: UIViewController = vc1 print(vc2. myNantokaField)
Avatar
omochimetaru 8/23/2017 8:54 AM
いや、オーバーライドする必要なくって
Avatar
↑が -1 になるんだと思ってる。違ったっけ? (edited)
Avatar
Swift3.xまでは動的ディスパッチっぽかった気がするけど
Avatar
omochimetaru 8/23/2017 8:55 AM
class Animal { var switcher: AnimalTypeSwitcher { switch self { case let cat as Cat: return .cat(cat) case let dog as Dog: return .dog(dog) default: fatalError("invalid") } } }
Avatar
あー
8:55 AM
全部あるからそれでいいな
8:55 AM
それを生成するだけでいいからいけるわ
8:55 AM
賢い。
Avatar
omochimetaru 8/23/2017 8:55 AM
class Animal { } // gyb extension Animal { var switcher: AnimalTypeSwitcher { switch self { case let cat as Cat: return .cat(cat) case let dog as Dog: return .dog(dog) default: fatalError("invalid") } } }
8:55 AM
最終形はこうかな
Avatar
Switcherはネストしてる方がお好き
Avatar
omochimetaru 8/23/2017 8:55 AM
賢い。
さっきその点を話してると思ってた。
Avatar
架空の俺が賢かったということでここは一つ。 (edited)
Avatar
omochimetaru 8/23/2017 8:56 AM
tarunon - 今日 午後5時44分 継承しているclass側に直に書かなくてもいいので omochimetaru - 今日 午後5時44分 var switcher を extentionでかいてもいいから gybでファイル分割してても問題ないね
Avatar
Swift4からextensionに書いたメソッドをoverride出来なくなりました
extension のメソッドが @objc なら出来ると思います。
9:32 AM
import UIKit extension UIViewController { @objc var foo: Int { return -1 } } class MyViewController : UIViewController {} extension MyViewController { override var foo: Int { return 1 } } MyViewController().foo // → 1
Avatar
QQ
Avatar
omochimetaru 8/23/2017 9:36 AM
キュッキュッ?
Avatar
ザハ先生ごめん…
9:36 AM
目玉飛び出してるAA
9:36 AM
台湾のかな?
Avatar
omochimetaru 8/23/2017 9:36 AM
👀
9:36 AM
:eyes:
Avatar
でもGenerics入れると@objc無理だし仕方が無い…仕方がなかったんや!
Avatar
protocol P0 {} protocol P1 : P0 {} func f0<X: P0>(_ x: X) {} func f1(_ x: P1) { f0(x) // compile error } func f2<X: P1>(_ x: X) { f0(x) }
Avatar
それはそうな気がする
Avatar
マジ?
10:39 AM
existential が 継承してる protocol を満たさない・・・
Avatar
Genericsな関数はconcrete typeが定まらないと
10:40 AM
使えんじゃんね
Avatar
でも f1(_ x: P1) は 制約じゃないよ
10:40 AM
f2のほうは制約だけど。
Avatar
f2におけるXは具体型になる
10:41 AM
f1はダメ
Avatar
プロトコル型の変数を作れるときは具体型としても振る舞うのかと思ってたけどそうじゃないんだなあ
Avatar
AnyP1/AnyP0にすればいけるよ。
10:42 AM
そりゃそうだけど
Avatar
いま手元で Array<P1> なプロパティがあって、 Array<X : P0> を受け取る関数に渡したいんだよね
Avatar
ArrayにProtocolをいれるのをやめろ!
10:43 AM
type-erasuresに詰めてください
😇 1
Avatar
自前のオブジェクトもしくは Int や Float 、みたいな型グループを取り回そうとしていた
Avatar
それenumの方が良くないか?と一瞬思ったけど
Avatar
拡張したいんよね
Avatar
まあprotocolでもいいか
10:44 AM
erasures最強erasures最強erasures最強!
Avatar
まあenumにするならどうせenumに詰めるアップキャストを明示的に書くからErasure用意するのとあんまかわらんか
10:44 AM
あしたやろ どうもでした。。
Avatar
protocol型のままArrayにつめるとか変数作るとか、出来ることは出来るんだけど変性周りで事故るから
😐 1
10:45 AM
erasureするのを強くおすすめしている。
Avatar
https://swift.org/blog/swift-local-refactoring/ の コンテキストメニューに "Add Missing Abstract Class Override" っていうのがあるんだけど、abstract クラスの前兆か?
Xcode 9 includes a brand new refactoring engine. It can transform code locally within a single Swift source file, or globally, such as renaming a method or property that occurs in multiple files and even different languages. The logic behind local refactorings is implemented entirely in the compiler and SourceKit, and is now open source in the swift repository. Therefore, any Swift enthusiast can contribute refactoring actions to the language. This post discusses how a simple refactoring can be implemented and surfaced in Xcode.
Avatar
マジ!!
11:23 AM
😄 2
Avatar
文明だ
Avatar
Xcode9 beta6 で実際にメニューにあるのは確認したんだけど、OSSリポジトリにその実装は無いのも確認しました。
😢 1
Avatar
omochimetaru 8/24/2017 2:49 AM
配列の中からダウンキャストできる最初の要素を取ろうとして animals.flatMap { $0 as? Cat }.first // キャストが全要素にかかって効率が悪い animals.first { $0 is Cat }.map { $0 as! Cat } // 効率的だけど冗長だし無駄な `!`
Avatar
@omochimetaru animals.lazy.flatMap { $0 as? Cat}.first
3:20 AM
↓最後まで回ってないことの確認 animals.lazy.flatMap { animal -> Cat? in print("a") return animal as? Cat }.first
👍 1
Avatar
omochimetaru 8/24/2017 3:21 AM
なるほど
Avatar
LazySequencemaprethrows がないのも(当然なんだけど)おもしろい。 https://developer.apple.com/documentation/swift/lazysequence/2905499-map (edited)
Avatar
omochimetaru 8/24/2017 3:22 AM
あ〜
3:22 AM
確かに。
3:22 AM
transformも @escaping になるわけか。
Avatar
うん。
Avatar
omochimetaru 8/24/2017 3:23 AM
ひーぷひーぷしてるから flatMapFirst を自作したほうがパフォーマンス的には理想的か
3:23 AM
計算量的には .lazy 作戦で最適だし特に自作しなくて良いのが楽で良いですね
Avatar
うーん、どれくらいパフォーマンスのボトルネックになってるか次第かな。
3:23 AM
よほどボトルネックでない限り lazy で良さそう。
Avatar
omochimetaru 8/24/2017 3:24 AM
まあそういう意味では他の処理の方が全然支配的なので最初に書いた効率の悪い方式にしました・・・
Avatar
画像処理の多重ループの中とかだと自作がいいだろうけど。
3:24 AM
まあでももはや自作じゃなくて for ループ書けばいい気もするけどw
Avatar
omochimetaru 8/24/2017 3:24 AM
取り出した要素をフィールドに格納したいのでforループだと微妙。
Avatar
omochimetaru 8/25/2017 2:09 AM
as によるキャストが失敗したときに例外が飛んで欲しい guardas? を組み合わせて書き下す事はできるけど、何箇所も出てくるなら部品化したい 関数にしてしまうと、 exp as Type の 左から右の流れが cast(exp, to: Type.self) のほうに カッコ閉じされてしまう
2:10 AM
=> を使って、 try exp => { try cast($0, to: Type.self) } にするというのがとりあえずの案だけど
2:11 AM
良い案は無いものか
Avatar
omochimetaru 8/25/2017 2:14 AM
as の代替ってわかりにくいですね
Avatar
func ==><T, U>(lhs: T, rhs: U.Type) throws U { guard let value = lhs as? rhs else { throw ... } return value } みたいな。
2:16 AM
==> という記号のわかりにくさをあきらめるか、 (edited)
2:16 AM
左から右の流れをあきらめるか、
2:16 AM
try exp => { try cast($0, to: Type.self) } の複雑さをあきらめるか、
2:16 AM
毎回 guard を書く面倒さをあきらめるか、
2:16 AM
どれかかな。
Avatar
omochimetaru 8/25/2017 2:17 AM
それだと => 採用だなあ
Avatar
これ一つで LT できそうだw
2:18 AM
その前に => の話が必要か。
Avatar
castを(Type)->(value)->castedにしたら=>で使いやすいのでは?
Avatar
omochimetaru 8/25/2017 2:21 AM
exp => cast(to: Type.self) こうですか
Avatar
try exp => cast(to: Type.self) にできる (edited)
Avatar
omochimetaru 8/25/2017 2:22 AM
ブレースが消えるしtryが一個減る・・・
Avatar
なるほど〜
Avatar
omochimetaru 8/25/2017 2:22 AM
ってか @autoclosure つけたらブレース無くせる?
2:23 AM
@autoclosure の中で $0 が書けなくてだめか
2:23 AM
それはいい案だけど単体のカリー化された cast 関数の何こいつ感がすごいな・・・
Avatar
できた。
2:30 AM
struct CastError: Error {} func cast<T, U>(to type: U.Type) -> (T) throws -> U { return { value in guard let value = value as? U else { throw CastError() } return value } } infix operator => : SwifletPrecedence precedencegroup SwifletPrecedence { higherThan: AssignmentPrecedence associativity: left } public func =><T, U>(lhs: T, rhs: (T) throws -> U) rethrows -> U { return try rhs(lhs) } let a: Int = 42 let b: Any = a print(try! b => cast(to: Int.self)) // 42 (edited)
2:31 AM
関係ないけど、なんで higherThan って higherthan じゃないんだろう?🤔
Avatar
omochimetaru 8/25/2017 2:32 AM
その Than ちょっと気になりますよね
Avatar
↑の cast 頭いいなぁ。黒魔術度は上がってるけどw
Avatar
omochimetaru 8/25/2017 2:33 AM
@t.ae はクロージャリテラルの { } を除去するの好きよね
Avatar
キャストのpostfix operator作って左辺値型推論させるのも綺麗にできそうですね
Avatar
omochimetaru 8/25/2017 2:33 AM
infix operator じゃ?
Avatar
型を書かないから、じゃない?
Avatar
let value = 0.0 let a: Int = try! value !!! (edited)
2:34 AM
こんなんできたら良いなと
Avatar
omochimetaru 8/25/2017 2:34 AM
なんだと・・・w
Avatar
try はいるんじゃない?
Avatar
tryは要りますね
Avatar
omochimetaru 8/25/2017 2:34 AM
=> のオーバーロードとして
Avatar
operatorである分かりにくさが問題
Avatar
omochimetaru 8/25/2017 2:35 AM
2引数の関数をうけたら
2:35 AM
いや、だめか
2:35 AM
いや、できるか?
Avatar
その前に => を標準ライブラリに入れたい
Avatar
omochimetaru 8/25/2017 2:35 AM
カリー化機能を => の方に持たせられれば
Avatar
例の Range のやつ止まってるけど、あれが終わったら提案してみよう。
Avatar
omochimetaru 8/25/2017 2:36 AM
=> の重要性を説得するの難しそう
Avatar
kotlinの先例があるし分かる人は多そうですが
Avatar
omochimetaru 8/25/2017 2:36 AM
kotlinはあんまりSwiftMLでも見ないよ
Avatar
プログラミングで頻出パターンだと思うけどなぁ。
2:37 AM
単に、ある式の結果を一つの式の中で複数回使いたいってことでしょ?
Avatar
kotlinユーザーが多いってことじゃなくて kotlinで採用されて便利だってことが認知されているということです
Avatar
omochimetaru 8/25/2017 2:37 AM
それだけなら関数で良いと思う
Avatar
let square = x() => { $0 * $0 }
Avatar
omochimetaru 8/25/2017 2:37 AM
中置演算子にするからパーレンネストがなくせて見やすいところがだいじ
Avatar
↑がやりたいことなんてよくあると思うけど。 (edited)
2:38 AM
ああ、関数じゃないところか。
Avatar
omochimetaru 8/25/2017 2:38 AM
func apply(x, f) = f(x) ではだめなんですよ
Avatar
まず、中置の重要性についてコンセンサスがとれてないといけないからなぁ。
Avatar
omochimetaru 8/25/2017 2:38 AM
あ、いやまあ、束縛するそれだけでも価値はありますけどね
Avatar
ここではコンセンサスがとれてるけど。
2:39 AM
Swift は中置がそれほど重視されていないからなぁ。
Avatar
omochimetaru 8/25/2017 2:39 AM
そうですかね
Avatar
Int(string) とか try foo() とか。
Avatar
omochimetaru 8/25/2017 2:39 AM
?. とかは、中置が重要って根っこでは思ってるから (edited)
2:39 AM
あるんじゃないですかね
Avatar
うーん、それを意識した構文設計なのか、それとも単に他言語で便利だったから持ってきたのか。
2:43 AM
まあ、 ns.map { $0 * $0 }.filter { $0 < 42 }.map { "\($0") }map(filter(map(ns) { $0 * $0 }) { $0 < 42 }) { "\($0)" }map({ "\($0)" }, filter({ $0 < 42 }, map({ $0 * $0 }, ns))) を比較して見せるだけで十分伝わる気もする。
2:44 AM
中置を採用するかどうかで可読性が違いすぎる。
Avatar
omochimetaru 8/25/2017 2:44 AM
たしかに。
Avatar
で、左から右に流れるように書きたいっていう意見の元で
2:45 AM
string => Int.init とかもできることも言えるし
2:46 AM
それはかえってネガティブかな?Int(string) 派との分裂を招くか?
Avatar
omochimetaru 8/25/2017 2:46 AM
左から右に流れるから読みやすいというより
2:46 AM
カッコがネストしてると、一個一個カッコの左と右の数を数えないと
2:46 AM
読み取れないことがつらい
2:47 AM
よく、 f(g(h(x), a)) と書くべきなのに f(g(h(x)), a) と書いてしまってコンパイルエラーになったりする。
Avatar
読みやすさだけじゃなくて書きやすさもあるかも。左から右に書けないと思考順と異なるから左に戻って書き足さないといけないのがめんどくさい。
Avatar
omochimetaru 8/25/2017 2:48 AM
たしかに。カッコで包むために←→をおすのが大変 (edited)
Avatar
左から右に読めることで関数名と合わせて文章的に理解できるのが良いんですよね
2:50 AM
メソッドチェーンで{}を少なくしたい理由もそこにある
Avatar
{} はクロージャ式?
Avatar
はい。
Avatar
↑と矛盾するようだけど、クロージャ式はチェーンしない方がいいと最近思ってる。
Avatar
omochimetaru 8/25/2017 2:51 AM
クロージャ式をチェーンとは?
Avatar
一段ずつ名前つけて変数(定数)に格納していかないと可読性が低すぎる。
Avatar
omochimetaru 8/25/2017 2:51 AM
すべてひっくり返しましたね
Avatar
さっきの例で言えば↓みたいな感じ。 let squares = ns.map { $0 * $0 } let filtered = squares.filter { $0 < 42 } let strings = filtered.map { "\($0") }
2:53 AM
まあこれくらいの処理なら連ねてもわかるけど
2:53 AM
もう少し複雑になるととたんにわからなくなる。
2:53 AM
特に型の変換が入ってると (edited)
Avatar
それと同じ話で、array.map { $0+1 }.map { $0+2 }array.map(addOne).map(addTwo)だと後者のほうが全体でどのような変換をしているのか文章的に理解できる
Avatar
omochimetaru 8/25/2017 2:53 AM
それやると、そういう処理が2つあったときに途中変数の名前がぶつかる まあやるなら do { } かな
Avatar
今、引数で受けてるのが何型なのかも考えないとわからない。
2:54 AM
そういう意味か < 関数名と合わせて文章的に理解できるのが良い
Avatar
mapじゃなくて=>だとよりわかりやすくなりますね
Avatar
=>map じゃないから代わりには使えないけどね。
Avatar
omochimetaru 8/25/2017 2:55 AM
array.map { addOne($0) }.map { addTwo($0) } でもそんな変わらない気がするけどな
Avatar
それにしてもなんか今日はここが社内 Slack 化してるな😅
😅 1
Avatar
=>だと someInteger => addOne => addTwoみたいにできて良さげ
Avatar
いや、それはさすがに someInteger + 1 + 2 でしょw
Avatar
無論もっと複雑な変換ですよ本当は
Avatar
omochimetaru 8/25/2017 2:58 AM
なんか Array と Optional のときだけそうやってかけるのに
2:58 AM
モナドに入ってない時だけ
2:58 AM
できないっていうのが
2:59 AM
=> が無いといけないって気持ちになるとき。
Avatar
bar(foo(x))x => foo => bar にできるってこと?
Avatar
omochimetaru 8/25/2017 2:59 AM
(無意味にSomeに入れて.mapをつなげるのは無し
Avatar
@koher yes
3:00 AM
それで一連の変換を文章として読解できる
Avatar
でもたいていは x.foo().bar() なんじゃないかなぁ。
3:00 AM
あんまフリーの関数作らない気がする。
Avatar
omochimetaru 8/25/2017 3:01 AM
レシーバが違うってことはありますよ
Avatar
ジェネリック関数とか
3:02 AM
さっきのキャストなんかはAnyのextensionができないですしね
Avatar
うん、なので順番として、
3:02 AM
普通は extension 作ればいいんだけど
Avatar
omochimetaru 8/25/2017 3:02 AM
hogehoge = try tag.mustFirstTag(name: "Hogehoge").mustFirstTag() => { try loader.mustResolveObject(tag: $0) => { try Hogehoge.from($0) } } ちょうど手元のコード
Avatar
Anyextension 生やせないから => が要るねって流れのはず。
Avatar
omochimetaru 8/25/2017 3:03 AM
最初の2処理は型が変わらないからメソッドチェーンだけど
3:03 AM
次の処理はloaderのメソッドになってるからチェーンにならない
3:03 AM
のでアローを使う
3:03 AM
その次も初期化系で同じく。
Avatar
他のインスタンスのメソッドってのはいい例ですね
Avatar
やっぱり変数に途中代入しておかないと可読性が・・・
Avatar
omochimetaru 8/25/2017 3:04 AM
マジすか?↑はめちゃめちゃ読みやすいと思っているんだけどなあ
Avatar
読めるけど、構造の理解にワンステップかかるから、少し理解が遅くなる。
3:06 AM
絶対↓の方が可読性高いと思う。 let fuga = try tag.mustFirstTag(name: "Hogehoge") .mustFirstTag() let hogehoge = try loader.mustResolveObject(tag: fuga) => { try Hogehoge.from($0) } (edited)
Avatar
omochimetaru 8/25/2017 3:07 AM
現実的には、これって、デコーダ的な処理なので
3:07 AM
このパターンが3つぐらい繰り返しているので
3:07 AM
名前衝突が生じてしまうのをさけるために
3:07 AM
let hogehogeTag = try tag.mustFirstTag(name: "Hogehoge") .mustFirstTag() let hogehoge = try loader.mustResolveObject(tag: hogehogeTag) => { try Hogehoge.from($0) }
3:08 AM
こうやってprefixで変数郡をグルーピングするか
3:08 AM
do { } スコープに閉じ込める必要が出るのと
Avatar
そこは↑で言ってたみたいに do ブロックで囲むか
Avatar
omochimetaru 8/25/2017 3:08 AM
この途中変数を、後段で参照される可能性が出て逆に読みづらくなる。
Avatar
もしくは個々を関数に切り出すのがいいんじゃないかなぁ。
3:09 AM
do で囲んでおくか関数に切り出せば「後段で参照される可能性」はなくなるよ。
Avatar
omochimetaru 8/25/2017 3:09 AM
そうですね
Avatar
do で囲むの大好き派。
3:09 AM
それで、できるだけローカルな短い名前を使う。
Avatar
doは外に書く変数宣言が気に入らない派
Avatar
omochimetaru 8/25/2017 3:09 AM
あとはdoにすると
3:09 AM
行数が間延びしちゃって
Avatar
@t.ae Kotlin みたいにしたくなるよね。
Avatar
omochimetaru 8/25/2017 3:09 AM
パット見がダラダラ長くて全体構造が読み取りづらい
Avatar
逆にdoでくくればxcodeの折りたたみがつかえて気に入ってるよ
Avatar
omochimetaru 8/25/2017 3:10 AM
doは外に書く変数宣言が気に入らない派
これは、doが式じゃないからってことだよね?
Avatar
val foo: Foo = run { val bar = ... val baz = ... Foo(bar, baz) }
Avatar
omochimetaru 8/25/2017 3:10 AM
doはそのdoによって発生する副作用がなんなのか
3:10 AM
わかりにくいのが問題なんだよね
3:11 AM
関数切り出しはわりとこれらの観点において全部クリアしているのでありだけど
3:11 AM
単純にタイピングが多すぎてだるい。
3:11 AM
@koher doよりはrunがいいですね、僕は。
Avatar
runはいいですね kotlinのとずれますが
Avatar
omochimetaru 8/25/2017 3:11 AM
そいつなら副作用は明確。
Avatar
あと型書かなくていいのが◎
Avatar
run でもキャプチャして書き換えられるのでは?
Avatar
omochimetaru 8/25/2017 3:12 AM
それはただのクソコードw
Avatar
それあるね。 < あと型書かなくていいのが◎
Avatar
omochimetaru 8/25/2017 3:12 AM
素直に読めばrunの返り値を作りたいんだなって感じるはずです
3:12 AM
doだと、わかんないんですよ、それが。
Avatar
じゃあ run を作れば解決では?
Avatar
omochimetaru 8/25/2017 3:12 AM
一番最後の行にあらわれるから
Avatar
func run<T>(_ f: () throws -> T) rethrows -> T { return try f() }
3:13 AM
run なら Swift でもできる。
3:13 AM
non-local return はできないけど、それは求めてないはず。
Avatar
omochimetaru 8/25/2017 3:13 AM
run + 中で let 分断代入はバランスいいと思います (edited)
Avatar
Swift だと最後に return 書かなきゃいけないのがちょい面倒。 (edited)
Avatar
そこはkotlinのほうが分かりにくいと思ってますがw
Avatar
まあ return ある方が可読性は高いかもしれない。
Avatar
omochimetaru 8/25/2017 3:15 AM
逆にdoでくくればxcodeの折りたたみがつかえて気に入ってるよ
↑これは・・・
Avatar
swiftの一行クロージャはreturn不要くらいがバランス良い気がします
Avatar
一旦未実装にしとくブロックに1行だけfatalError()って書いといたらreturnを省略したと思われたのかNeverを返すなって言われてreturn必須でもいいんじゃねーのって気になっている
Avatar
個人的には↓でも意図は十分明確だと思うけどなぁ。 let foo: Foo do { ... foo = Foo(...) }
Avatar
omochimetaru 8/25/2017 3:16 AM
1文クロージャがvoid返り値にならずに変なことになるのあるある
Avatar
そこは _ =
Avatar
omochimetaru 8/25/2017 3:16 AM
それならrun使いますね・・・
Avatar
十分明確だと思うけどなぁ。
僕も普段違和感なくこういうの書いてますね
Avatar
スコープの中で何か変更しちゃうのも、 run でも起こりうるし。
Avatar
omochimetaru 8/25/2017 3:17 AM
fooを2回書くのと、fooの右の型:Fooを書くのが冗長
3:17 AM
最後の行の foo = まで確認しないと、本当にlet foo がその下のdoで代入したいものなのかわからないし。
Avatar
foo を 2 回書くは run でも return 書いてるよ。
Avatar
omochimetaru 8/25/2017 3:17 AM
てことは、doを読む前にfooを覚えておかないといけない。
3:18 AM
たしかに・・・ > return
3:18 AM
いや、ちがうな returnは
3:18 AM
名前の同一性を考える必要はないです
Avatar
型を書くのが面倒、意図が明確ってのはあるけど
Avatar
omochimetaru 8/25/2017 3:18 AM
ただの共通の制御命令なので。
3:18 AM
let do パターンは、 一つ目のfooと2つめのfooの名前同一性の確認が必要です。
3:18 AM
あ、わりとあるのは、コピペして、それを2回やったときに
Avatar
非標準のものを導入することで初見殺しになるのと天秤にかけたら、まあ do でもいっかなってなる。
Avatar
omochimetaru 8/25/2017 3:19 AM
2こめのletと最後のところの foobaz に書き直したりする時に
3:19 AM
渋い気持ちになる。
Avatar
なるほど。コピペ面倒はあるかも。
Avatar
omochimetaru 8/25/2017 3:19 AM
run なら return は共通だし、型も推論されるから、冒頭の左辺の変数名だけの修正でいい
Avatar
letならコンパイルエラーなるし修正漏れてバグることは無いはずだし良いと思うけどなー 治すのが面倒なのはそうかも
Avatar
標準ライブラリに run があればそれ使えばいいだけの話なので、提案して通して下さい👍
Avatar
omochimetaru 8/25/2017 3:20 AM
非標準のものを導入することで初見殺しになるのと天秤にかけたら
初見さんはちゃんとそのプロジェクトで使ってるユーティリティは最初に学ぶべきだと思ってるなあ 例えばその理論だとRxとか使えなくなっちゃうし。
3:21 AM
それが1箇所だけとかならいいけど、何度も出てきて効用が大きくなってくるなら導入しちゃったほうが
3:21 AM
初見殺しコストよりメリットが大きくなる
3:21 AM
runは別に標準になくてよくて、internalで定義するからいいんですよね
3:22 AM
=>
3:22 AM
演算子が internal にならないから
3:22 AM
標準に欲しい。。
Avatar
最近実は internal になるような気もしてるんだけど、真相はわかってない・・・
3:23 AM
import しないと演算子使えないよね?そしたら同じ演算子 import しなければ
3:23 AM
異なる precedence でも共存できたりしない?
3:23 AM
もちろん、一つのファイルで衝突したらダメだけど。 (edited)
Avatar
omochimetaru 8/25/2017 3:25 AM
最初そう思ったら @koher がいや演算子は駄目で、、、って言ってたからそう思ってたけど検証はしてないのでよくわからない
Avatar
プロジェクトローカルであればカスタム演算子作っても全然いいと思うけどね。 run 作るのと変わらなさそう。
Avatar
operator 宣言自体は常に public ですね。
Avatar
omochimetaru 8/25/2017 3:45 AM
なんかいけるっぽいぞ。
Avatar
ただ、 たとえば https://github.com/thoughtbot/Runes を import した モジュールを import しても Runes の演算子はつかえない。
Runes - Infix operators for monadic functions in Swift
Avatar
omochimetaru 8/25/2017 3:47 AM
Contribute to swift-operator-isolation-verify development by creating an account on GitHub.
Avatar
そういえば Swift のパッケージの間接的な import ってどう働くのかよくわかってないです。 Fooimport してる Bar があったとして、 Barimport しても Foo は使えないと思ってるんですが、 Obj-C との兼ね合いで(?) UIKitimport したら Foundation も使えるとかありますよね?
Avatar
@_exported import Foundation とか。
Avatar
おお、そんなのがあるんですね。
Avatar
@_exported つけると、Bar@_exported import Foo してたら、 Bar だけ import すれば Foo も使えます。 (edited)
🙂 1
3:54 AM
あと extension まわりだと https://bugs.swift.org/browse/SR-3908 バグもあり、ちょっと混乱しますよね。
3:55 AM
// ModuleA public extension Array { public var first: Element? { return nil } } // ModuleB import ModuleA // main import ModuleB let a = [1,2,3].first // -> nil っていう問題。
Avatar
↑これヤバイですね。
Avatar
omochimetaru 8/25/2017 3:56 AM
@_exported でできるのか
3:57 AM
C / Clang 系の modulemap だとexport制御があるけど
3:57 AM
Swift言語上だとそれらの機能いろいろ足りないよなと思っていた
3:58 AM
https://github.com/omochi/swift-operator-isolation-verify@koher ライブラリごとのオペレータ制御に特に問題なく独立importできるように見える
Contribute to swift-operator-isolation-verify development by creating an account on GitHub.
3:59 AM
Animalライブラリでinfix => と prefix => を定義してて、 Materialライブラリでも infinx => と prefix => を定義してて
3:59 AM
Appアプリのmodule0.swiftでimport Animalとmodule1.swiftでimport Materialで
3:59 AM
それぞれ違う動作する
4:01 AM
なのでSPM環境ならSwiflet を取り込めばいいし、コピペでソース取り込みでも、普通のクラスや関数と同じように、特に問題ない気がする
Avatar
precedence 変えたりしてもちゃんと動くのかな?
Avatar
omochimetaru 8/25/2017 4:01 AM
やってみるか
Avatar
前に動かなかったのは Runes と同じように設定して両方読み込んで動かなかったのかも。
Avatar
operator 宣言とその演算子の実装 public func が別モジュールにあるといろいろ混乱する気がする。
Avatar
operator の宣言自体は重複しても問題はないんですか?
Avatar
omochimetaru 8/25/2017 4:05 AM
これってhigherThanだけだとだめか?
Avatar
あ、あと関係ないんですけど、さっき話してたんですけど higherThanhigherthan じゃない理由とか知ってたりします?他のキーワードと一貫性がない気が。
Avatar
@omochimetaru App で Material と Animal を両方 import するファイルだとどうなります?
Avatar
omochimetaru 8/25/2017 4:05 AM
ちょっとまってて・・・
4:05 AM
/Users/omochi/github/omochi/swift-operator-isolation-verify/Sources/app/module0.swift:3:10: error: adjacent operators are in unordered precedence groups 'SwifletPrecedence' and 'AdditionPrecedence'
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
camelCase なのはどうしてかっていう話ですよね?
Avatar
omochimetaru 8/25/2017 4:07 AM
[omochi@omochi-iMac swift-operator-isolation-verify (master *%=)]$ swift run Compile Swift Module 'app' (4 sources) /Users/omochi/github/omochi/swift-operator-isolation-verify/Sources/app/module2.swift:4:10: error: ambiguous operator declarations found for operator print(1 => 2 + 3) ^ <unknown>:0: note: found this matching operator declaration <unknown>:0: note: found this matching operator declaration /Users/omochi/github/omochi/swift-operator-isolation-verify/Sources/app/module2.swift:4:10: error: operator is not a known binary operator print(1 => 2 + 3) ^ /Users/omochi/github/omochi/swift-operator-isolation-verify/Sources/app/module2.swift:4:10: error: ambiguous use of operator '=>' print(1 => 2 + 3) ^ Animal.=>:1:13: note: found this candidate public func =>(a: Int, b: Int) -> Int ^ Material.=>:1:13: note: found this candidate public func =>(a: Int, b: Int) -> Int ^ error: terminated(1): /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-build-tool -f /Users/omochi/github/omochi/swift-operator-isolation-verify/.build/debug.yaml app.exe
4:07 AM
両方importするとエラーですね
Avatar
camelCase にしない複合語のキーワードは他の識別子と衝突しないから筋がいいと思うんですが、ここだけ higherThan なのが謎・・・
Avatar
omochimetaru 8/25/2017 4:08 AM
Contribute to swift-operator-isolation-verify development by creating an account on GitHub.
4:08 AM
できた
4:08 AM
Precedenceが違っても特に問題ない
4:08 AM
両方importしてる場合は、 => の呼び出しで、オーバーロードが曖昧ってエラー (Source/App/module2.swift) (edited)
Avatar
おお、素晴らしい
Avatar
omochimetaru 8/25/2017 4:09 AM
あと、Precedenceは、higherThanだけだと、混ぜて使ったときにエラーになることがわかった
Avatar
<unknown>:0: note: found this matching operator declaration <unknown>:0: note: found this matching operator declaration このエラーはだめだー
Avatar
omochimetaru 8/25/2017 4:09 AM
swifletにlowerThanも書いたほうが良さそう。
Avatar
混ぜて使ったときにエラーになる
何と混ぜて?
Avatar
omochimetaru 8/25/2017 4:10 AM
+と。
4:10 AM
再現きるのでまってて
Avatar
ああ
4:11 AM
+ とはあえて優先順位をつけてない
Avatar
precedence をグラフ化したときに、合流していない枝にある演算子同士を混ぜるとエラーになる。 (edited)
Avatar
omochimetaru 8/25/2017 4:11 AM
infix operator => : SwifletPrecedence precedencegroup SwifletPrecedence { associativity: left higherThan: TernaryPrecedence } // alias multiple public func =>(_ a: Int, _ b: Int) -> Int { return a * b } print(3 => 2 + 1) (edited)
Avatar
let r = x() => { $0 * $0 } + y() => { $0 * $0 }
Avatar
omochimetaru 8/25/2017 4:12 AM
a.swift:14:9: error: adjacent operators are in unordered precedence groups 'SwifletPrecedence' and 'AdditionPrecedence' print(3 => 2 + 1) ^ ~
Avatar
↑みたいなのがあったときに
4:12 AM
=>+ のどっちが早いかは感覚的にも自明でないので
4:12 AM
明示的に () を付けさせる。
Avatar
omochimetaru 8/25/2017 4:12 AM
precedence をグラフ化したときに、合流していない枝にある演算子同士を混ぜるとエラーになる。(編集済)
難しい・・・
4:13 AM
どういうことだ・・・???
Avatar
そもそも、そんなに複雑な式で使うと可読性を損ねる
Avatar
omochimetaru 8/25/2017 4:13 AM
オペレータ同士の強弱が1本のルールに並んでないってこと??
Avatar
↓にすればいい let r = (x() => { $0 * $0 }) + (y() => { $0 * $0 })
4:13 AM
うん
Avatar
omochimetaru 8/25/2017 4:13 AM
マジか
Avatar
それが Swift の今の precedence のいいところ
Avatar
omochimetaru 8/25/2017 4:13 AM
いいところなのそれ・・・
Avatar
元々並んでたのを
4:14 AM
あえて並ばないようにした。
Avatar
omochimetaru 8/25/2017 4:14 AM
てっきり、整数で定義するのだとややこしいから、 > で定義しただけかと
4:14 AM
おもってた
Avatar
それによって、関連性のない複数の演算子間で
Avatar
omochimetaru 8/25/2017 4:14 AM
一つの並びですらなくなってしまったのか
Avatar
無理やり優先順位を決めなくて良くなった。
4:14 AM
そういう直感に反するものは
4:14 AM
混ぜて使うとコンパイルエラーとして検出できて
4:14 AM
書いている人の意図に合わせて () を付けて解決する。
4:15 AM
これによって、演算子の優先順位が想定外なことによる
4:15 AM
バグを防ぐことができる。
Avatar
omochimetaru 8/25/2017 4:15 AM
そうすると
4:15 AM
precedencegroup SwifletPrecedence { associativity: left higherThan: TernaryPrecedence }
4:15 AM
この定義微妙?
Avatar
+* とか、当然関連があってほしいものには優先順位が決められるけど
Avatar
omochimetaru 8/25/2017 4:16 AM
?: Ternary conditional Right associative TernaryPrecedence
4:16 AM
Ternaryって?:ですけど
4:16 AM
lowerThan: AssignmentPrecedence
4:16 AM
にして
4:16 AM
a = b => c 形式だけ定義したほうがいい?
Avatar
それ @omochimetaru の改造でしょ?
Avatar
omochimetaru 8/25/2017 4:16 AM
いや、 ?: との関連なのに、代入文と混ぜられる理由がわからなくなってきた
Avatar
swiflet - Provides => like let in Kotlin for Swift
Avatar
omochimetaru 8/25/2017 4:17 AM
ああ本家はASsignmentなのか
Avatar
あ、ちなみに↑の優先順位の決め方の利点は、 Proposal 読んでないけどおそらくそういうことだろうと予想しているだけなので、確証はないです。
Avatar
omochimetaru 8/25/2017 4:18 AM
HigherThan Ternaryで = とは一緒に使えるのに
4:18 AM
+ とは一緒に使えないのは
4:18 AM
うーん、グラフの図がないとどこに枝がわかれてるのかようわからんな
4:19 AM
あー
4:19 AM
いや、わかってきた
Avatar
+=> もより優先順位が高いだけで
4:20 AM
どっちが高いのか決まらない。
Avatar
omochimetaru 8/25/2017 4:20 AM
=> >> ?: >> = だけど + >> ?: でもあるから、 =>+ の関係が不明なのか。
4:21 AM
Swift言語組み込みの既存のオペレータは、全部繋がってるんですかね?
4:21 AM
下位互換あるはずだから多分そうだよな
Avatar
三項演算子の左オペランドの式に+ を書くことなんてないから三項演算子と + の間では優先順位が決められてないかと思ったけど決められてた。 func +(lhs: Bool, rhs: Bool) -> Bool { return lhs || rhs } true + false ? 2 : 3 // 2
4:22 AM
@omochimetaru 下位互換がないのが Swift のメジャーアップデートでは?w
Avatar
omochimetaru 8/25/2017 4:22 AM
まあそうだけどここでやってたら死体が多すぎそう
Avatar
a | / \ b c | | d | \ / | e こういうグラフだと a-b-d-e もしくは a-c-e は使えるけど b-c とかは使え無い。
4:23 AM
precedence をグラフ化したときに、合流していない枝にある演算子同士を混ぜるとエラーになる。
↑ちょっと違いました。
Avatar
omochimetaru 8/25/2017 4:23 AM
a higherThan b と定義するのと b lowerThan a と定義するのは等価ですか?
Avatar
そこで矛盾するとどうなるんだろう?🤔
4:24 AM
後に出てきた方しか先の方を参照できないのかな?
Avatar
どうなるんだろう。。
Avatar
Swift 以外にこういう演算子の順序付けしてる言語あるのかな?
Avatar
omochimetaru 8/25/2017 4:26 AM
infix operator +++ : PikaPlusPrecedence infix operator *** : PikaStarPrecedence precedencegroup PikaPlusPrecedence { associativity: left higherThan: PikaStarPrecedence } precedencegroup PikaStarPrecedence { associativity: left higherThan: PikaPlusPrecedence }
4:26 AM
[omochi@omochi-iMac sw-op-def]$ swift a.swift a.swift:11:5: error: cycle in higherThan relation: PikaStarPrecedence -> PikaPlusPrecedence -> PikaStarPrecedence higherThan: PikaPlusPrecedence ^
Avatar
error: cycle in higherThan relation: B -> A -> B
Avatar
omochimetaru 8/25/2017 4:26 AM
賢いな・・・
4:26 AM
infix operator +++ : PikaPlusPrecedence infix operator *** : PikaStarPrecedence precedencegroup PikaPlusPrecedence { associativity: left higherThan: PikaStarPrecedence } precedencegroup PikaStarPrecedence { associativity: left lowerThan: PikaPlusPrecedence }
4:27 AM
[omochi@omochi-iMac sw-op-def]$ swift a.swift a.swift:11:16: error: precedence group cannot be given lower precedence than group in same module; make the other precedence group higher than this one instead lowerThan: PikaPlusPrecedence ^ a.swift:4:17: note: precedence group declared here precedencegroup PikaPlusPrecedence { ^
4:27 AM
冗長に逆方向も定義しようとしたら怒られた
4:27 AM
同じモジュールの中の演算子同士のlowerThanは定義できないよ、代わりにhigherThanで定義してね とのこと (edited)
Avatar
へぇ、そうなんだ。
Avatar
omochimetaru 8/25/2017 4:28 AM
ようできとるな
4:28 AM
柔軟だし定義したことだけ動くし定義不足ならそれ で困ることが起きるときにエラーになる (edited)
Avatar
ほんと最近の Swift は細かいところがよくできてるなぁと思う。
4:29 AM
higherThan の camelCase だけ謎。 (edited)
Avatar
omochimetaru 8/25/2017 4:29 AM
associatedtype とかも小文字だしなあ 本当にそれだけか
Avatar
もしかしてみんな見逃してしまったまま通っちゃったんじゃあ・・・。
4:29 AM
camelCase にすると識別子と衝突しかねないから良くないと思う。
Avatar
precedencegroup内にしか書かないからそういうことは無さそうですが……
Avatar
まあ Swift は予約語にして外でも使用禁止にしないから大丈夫か?
Avatar
omochimetaru 8/25/2017 4:31 AM
@discardableResult
Avatar
それでも一貫性はない
Avatar
omochimetaru 8/25/2017 4:31 AM
アットマークがついてるからセーフか?
Avatar
@omochimetaru それは Attriute だから
4:31 AM
キーワードでは他に camelCase はないと思う。
4:31 AM
associatedtype, typealias, precedencegroup, ...
4:33 AM
識別子としては普通に使えそう func higherThan<T: Comparable>(_ x: T, _ y: T) -> Bool { return x > y } higherThan(3, 2) // true
4:33 AM
ここか?
Avatar
@omochimetaru yes
Avatar
omochimetaru 8/25/2017 4:34 AM
さがしてた
4:34 AM
higherThanがない
Avatar
precedencegroup 内だけなので higherThan はキーワードではなくて、いったん identifier としてトークン化されてパーサーで特別扱いです。
Avatar
なるほど。
4:36 AM
識別子なら camelCase でも自然なのか
4:37 AM
居た
4:39 AM
higherThan、カンマで並べられたのか
Avatar
higherThan、カンマで並べられたのか
しらなかったー
Avatar
omochimetaru 8/25/2017 4:40 AM
infix operator +++ : PikaPlusPrecedence infix operator *** : PikaStarPrecedence precedencegroup PikaPlusPrecedence { associativity: left higherThan: PikaStarPrecedence, AssignmentPrecedence } precedencegroup PikaStarPrecedence { associativity: left }
4:40 AM
コンパイルできた。
4:41 AM
do { if (!Tok.is(tok::identifier)) { diagnose(Tok, diag::expected_precedencegroup_relation, attrName); return abortBody(); } auto name = Context.getIdentifier(Tok.getText()); auto loc = consumeToken(); relations.push_back({loc, name, nullptr}); } while (consumeIf(tok::comma)); ここの最後の行見てわかったw
4:48 AM
infix operator <-= : AssignmentPrecedence func <-= <T> (_ lvalue: inout T, _ rvalue: T) -> T { lvalue = rvalue return lvalue } var x: Int = 1 let y = x <-= 3 print("x=\(x)") print("y=\(y)")
4:48 AM
[omochi@omochi-iMac sw-op-def]$ swift a.swift x=3 y=3
4:48 AM
代入結果を返す代入演算子作れる!!
4:48 AM
これを使えばこの前のkoherのパターンが
Avatar
<= じゃダメ?
4:49 AM
すでにあるっけ?
Avatar
omochimetaru 8/25/2017 4:49 AM
<= Less than or equal None ComparisonPrecedence
4:49 AM
それあるんだよな・・・
Avatar
あれ?そうか
Avatar
omochimetaru 8/25/2017 4:49 AM
ww
4:49 AM
いや絶対めっちゃ使用経験ある
4:49 AM
if i <= 2 { return }
Avatar
=< とか?
Avatar
omochimetaru 8/25/2017 4:50 AM
代入系は全部一番右が = だからそれに習ってみた
Avatar
:=ができたらいいんですけどね
Avatar
<-はよさそう
Avatar
omochimetaru 8/25/2017 4:51 AM
Luaかな
Avatar
Haskell 的にはモナドを剥がして束縛だけどね
Avatar
omochimetaru 8/25/2017 4:52 AM
var cache: Int? let v = (cache <-= cache ?? 3)!
4:53 AM
こいつをつかうと、キャッシュが無かったら初期化してキャッシュとして保存しつつその結果を保持、が、1発で書けるよ。
4:53 AM
! が必要だけど・・・
Avatar
あえて Swift が禁止した = の戻り値を復活させるなんてw
Avatar
omochimetaru 8/25/2017 4:54 AM
見た目が = じゃないからOK
Avatar
willSet didSet が動いちゃう問題
Avatar
omochimetaru 8/25/2017 4:55 AM
private var にして stored property にするしかないですね
4:55 AM
いや、いずれにしても、2回目以降の代入が無駄か
Avatar
omochimetaru 8/25/2017 6:17 AM
func f0(_ f: ( (Int) throws -> (), Int) ) rethrows -> Int // error (edited)
6:17 AM
rethrowsは、throwsが引数に直接ついてないとだめなんですね
6:20 AM
あれ!
6:20 AM
func add(_ x: Int, _ y: Int) -> Int { return x + y } print((1, 3) => add) これできるのか
6:20 AM
関数の引数をタプルとして扱える仕様なくなったと思ってた
6:21 AM
public func =><T0, T1, R>(_ x: T1, _ f: ((T0, T1) -> R, T0)) -> R { return f.0(f.1, x) } print(3 => (add, 1)) (edited)
6:21 AM
@t.ae こんなのはどうかな (edited)
Avatar
外で部分適用するわけですか
Avatar
omochimetaru 8/25/2017 6:22 AM
うん。演算子にタプルを取る版を組み込むことで、圧倒的に短く書ける
6:22 AM
カリー化版を用意するという気持ち悪さを回避
6:23 AM
ただrethrowsができないのでthrows版を作らないといけないけど、まあgybでつくるので問題なし
Avatar
cast に限って言えばカリー化で十分な気が。
Avatar
omochimetaru 8/25/2017 6:24 AM
一般的に使えたら便利かなと => が、関数を中置にする一般的な道具となる
Avatar
/とか左右同じ型だけど非可換のとき分かりにくいかも?
Avatar
omochimetaru 8/25/2017 6:25 AM
どっちが部分適用されてるのかよくわからんってことだよね
Avatar
そうです
Avatar
omochimetaru 8/25/2017 6:25 AM
それは思った。。
Avatar
まぁ左から右と思うようにすればいいですけど
Avatar
omochimetaru 8/25/2017 6:25 AM
この場合 1 + 3 になっているので
6:26 AM
逆だねw
Avatar
確かにw
Avatar
omochimetaru 8/25/2017 6:26 AM
まあたしかに、第一引数だけ左に出したって考えるほうがわかりやすいか
6:27 AM
print(4 => (sub, 1) ) // 3 (edited)
6:27 AM
これで 4 sub 1 の並びになるしね
Avatar
うーん、ちょっと複雑すぎな気が
6:28 AM
4 => { $0 - 1 } で十分そう。
Avatar
hakellみたいに4 `sub` 1ができたら良いんですけどね
Avatar
omochimetaru 8/25/2017 6:28 AM
あ、subは例なので、もっと複雑な何行もある処理を想定 (edited)
6:28 AM
4 => { sub($0, 1) }
Avatar
複雑な処理だとしたら、クロージャ式じゃなくて関数渡す話?
Avatar
omochimetaru 8/25/2017 6:29 AM
そうですね
Avatar
それとも non-trailing なクロージャ式を渡すの?
Avatar
omochimetaru 8/25/2017 6:29 AM
ん?
6:29 AM
あーそういうことか
Avatar
4 => { foo($0, 1) } でも全然いい気がする。
6:30 AM
try があると面倒なのか
Avatar
omochimetaru 8/25/2017 6:30 AM
いやなんか、 1引数のときだけ 4 => twice が書けるのが気持ち悪くて。
6:30 AM
あ、そうですね、右側の try が消せるっていうメリットもある。
Avatar
try 4 => { try foo($0, 1) }
Avatar
omochimetaru 8/25/2017 6:30 AM
2引数のときも同じ形式が書けるのでなければ、1引数のときだけ { } を消すのは嫌で
6:30 AM
逆に2引数のときに { } を消せたらいいなと思って考えていた
Avatar
1引数のときだけ 4 => twice が書けるのが気持ち悪くて。
そのために導入するには複雑すぎる気がするなぁ。
6:32 AM
4 => { foo($0, 1) } は何やってるかひと目でわかるけど、 4 => (foo, 1) はちょっと考えてしまいそう。
6:32 AM
foo のコールがないから関数なのもわかりづらいし・・・
Avatar
omochimetaru 8/25/2017 6:32 AM
4 => foo これもひと目ではわからないと思う
Avatar
それだったらカリー化の機能を => に持たせて
6:33 AM
(4 => foo)(1)
6:33 AM
の方がまだいいかも。
Avatar
omochimetaru 8/25/2017 6:33 AM
4 => { foo($0, 1) } は、fooのコールも { } も普通だから、だいぶわかりやすいですね
6:33 AM
4の左にカッコを書きたくない・・・
6:33 AM
適用は見えてるからわかりやすいけど
Avatar
4 => foo=> を使うために最低限知っているべきことな気が。
Avatar
omochimetaru 8/25/2017 6:34 AM
(4 => foo)(1) これ自体は演繹的なのはいいですね
6:34 AM
もともとの挙動と一般化して考えられる
Avatar
大体、そういうパターンも考え出すと↓みたいなのがほしくなるんじゃないの?
6:35 AM
(x(), y()) => foo
Avatar
omochimetaru 8/25/2017 6:35 AM
それはすでにできるんですよ
6:35 AM
驚いたことに
6:35 AM
さっきそれで驚いた。
Avatar
ああ、それなら
6:36 AM
いやちがうな
6:36 AM
それできるのって正しいんだっけ?
Avatar
omochimetaru 8/25/2017 6:36 AM
僕もいろいろあって消えた概念だと思ってた
Avatar
そのあたりグダってたから一時的に復活してるだけでは?
Avatar
omochimetaru 8/25/2017 6:36 AM
マジ?
Avatar
クロージャ式で受けるときにタプル展開できないと辛い話が再燃して
6:37 AM
一時禁止されてたのを戻そうということになったけど
6:37 AM
決着ついてるんだっけ?
Avatar
omochimetaru 8/25/2017 6:38 AM
func apply<T, R>(_ x: T, _ f: (T) -> R) -> R { return f(x) } func sub(_ x: Int, _ y: Int) -> Int { return x - y } print(apply((4, 1), sub))
6:39 AM
IBM Swift Sandbox だと、 3.0, 3.1, 3.1.1, 4.0 で動きます
6:50 AM
これとは逆なので、微妙なところかも
Avatar
omochimetaru 8/25/2017 6:50 AM
これって引数をタプルで受ける話で
6:50 AM
引数にタプルを当てる話しは
6:51 AM
関係ない?
Avatar
func foo(x: Int, y: Int) { } let a: ((Int, Int)) -> Void = foo これが成立しちゃうのは、たしか SE-110 が revert される前でも起きていて、SE-110 が議論中だったので報告迷った覚えがあります。
Avatar
omochimetaru 8/25/2017 6:53 AM
なるほど
Avatar
https://bugs.swift.org/browse/SR-5130 バグとして扱われている
Avatar
omochimetaru 8/25/2017 6:59 AM
let b: ((Int, Int)) -> Int = add // OK, but why isn't it an error? これがバグとされるなら、さっきのもバグっぽいですね
8:02 AM
Swiftの中で if case let 使ってるとこみつけた
8:02 AM
珍しい
8:03 AM
この行ラトナだ
Avatar
if case let printableObject as CustomStringConvertible = value { か。↓にしてしまいそう。 if let printableObject = value as? CustomStringConvertible {
Avatar
なぜ if let ... = ... as? .. { にしなかったんだろう。っていうか switch のほうが良い気がする。
Avatar
omochimetaru 8/25/2017 8:07 AM
ですね、僕もそう書く > as? (edited)
8:08 AM
switch case だと一番最初の
8:08 AM
if _isOptional(type(of: value)) {
8:08 AM
このパターンは case にできなそう?
Avatar
でも if let foo = foo は Swift の構文の失敗だと思うから使いたくない気持ちはわかる。
Avatar
omochimetaru 8/25/2017 8:09 AM
www
8:09 AM
2年前のラトナーもそう考えていたのか・・・?
Avatar
swift-evolution のどこかで、今なら違う構文にするって言ってたような?
Avatar
omochimetaru 8/25/2017 8:09 AM
2年前に if let as? あったっけ
8:10 AM
Chris Lattner committed on 10 May 2015
Avatar
if let foo = foo { より if case let foo? = foo { の方が好き。
8:11 AM
書くときは前者で書いちゃうけど。
8:12 AM
let 書いたらパターンマッチとして case 省略とかできないのかな。
8:12 AM
if let foo? = foo { これ↑だといいんだけどなぁ。
8:13 AM
Optional binding は = の左右で型が変わってるのが気持ち悪い・・・。
Avatar
2年前に if let as? あったっけ
これは 1.0 より前からありました。
Avatar
omochimetaru 8/25/2017 8:13 AM
なるほど、じゃあラトナーがあえて if case let を選択してるわけですね
Avatar
スマートキャストがあったらif case foo? {とかよさそう
Avatar
途中で追加されたのは as? じゃなくて as! か。
8:14 AM
trytry! が先で try? が後。
8:15 AM
スマートキャストは納得できない理由で否定されてた気が。
8:15 AM
定義にジャンプで型が確認できなくなるから、とか。
8:15 AM
そんなんだった気がする。
8:16 AM
スマートキャストされたところにジャンプしてくれれば済む話のはず。
Avatar
isのスマートキャストはともかくOptionalのアンラップにとんでも何だこれってなりそう
Avatar
1, 2 ヶ月に 1 回くらいスマートキャストほしくなる。
Avatar
ちなみにどっちの構文でも silgen 結果はまったく変わらなかったです。
Avatar
omochimetaru 8/25/2017 8:22 AM
なるほど。
Avatar
おお、そうなんですね。じゃあ何かの最適化のためとかでもなく、単純な構文の好みということですね。
Avatar
あれ? Double.pi はあるけど Double.e はないんだっけ?
8:53 AM
M_E ってどうやってとるんだっけ?
8:54 AM
M_E にするしかない??
Avatar
warningでおしえてくれそう (edited)
8:56 AM
ジェネリックな sin 関数とかもないですよね
8:56 AM
eってpowとかlogから取り出せないんだっけ
Avatar
sinはFoundationにはいってたような
Avatar
omochimetaru 8/25/2017 8:58 AM
これ謎なんだよな オーバーロードされてるやつ
Avatar
変なの
9:01 AM
とりあえずアプリの extension の中にいれておくか < e
Avatar
omochimetaru 8/25/2017 9:01 AM
sin と sinf が見えてるのは、math.hからきたやつだとおもうんですけど
9:01 AM
sin の doubleとfloatのオーバーロードもあるんですよね
Avatar
いつも Unsafe(Mutable)Pointer<T>Unsafe(Mutable)Pointer<U> に変換する方法を忘れてしまう・・・
Avatar
omochimetaru 8/25/2017 9:45 AM
bindMemoryですか?
9:46 AM
ちょうど昨日間違った情報にツッコミをいれました http://qiita.com/codelynx/items/64dd046f61267e9905e2
UnsafeMutableRawPointer から UnsafeMutablePointer にキャストする方法をずっと悩んでいましたが、やっとわかったので、ここにメモしておきます。 わざとらしいコードですが、一旦 ...
Avatar
一度 RowPointer を介して bindMemory するんだっけ?
9:46 AM
介さないでいけますよ
9:47 AM
let uint64Pointer: UnsafeMutablePointer<UInt64> = fetchValue() let isNegative = uint64Pointer.withMemoryRebound(to: Int64.self) { ptr in return ptr.pointee < 0 } (edited)
Avatar
withMemoryRebound のクロージャ式は何のためにあるの?
Avatar
omochimetaru 8/25/2017 9:55 AM
その中でしかそのポインタを使ってはいけないです
Avatar
あー
9:55 AM
なるほど
Avatar
omochimetaru 8/25/2017 9:55 AM
The closure’s pointer argument is valid only for the duration of the closure’s execution
Avatar
↑のコード capacity なくない?
Avatar
omochimetaru 8/25/2017 9:58 AM
func withMemoryRebound<T, Result>(to: T.Type, capacity: Int, (UnsafeMutablePointer<T>) -> Result)
9:58 AM
capacity引数ありますよ、↑はdefault=1かな
Avatar
default がついてないように見えるんだけど。
Avatar
omochimetaru 8/25/2017 9:59 AM
本当だ
9:59 AM
じゃあこのドキュメントは古いですね
10:00 AM
これめっちゃ最近提案されてたやつだと思います capacity = 1
Avatar
そうなんだ。
10:01 AM
消えてるw
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
10:01 AM
これの Detailed Designのところ (edited)
10:02 AM
--- func withMemoryRebound<T, Result>(to:T.Type, count:Int, _ body:(UnsafeMutablePointer<T>) -> Result) +++ func withMemoryRebound<T, Result>(to:T.Type, count:Int = 1, _ body:(UnsafeMutablePointer<T>) -> Result) (edited)
10:02 AM
デフォルト1が付け足されるらしい。
10:02 AM
いや、逆かな?最初はcountがなくて、ドキュメントが書かれて、途中でcountが増えて、これで改めてdefault = 1になったのかも?
Avatar
↑、コアチームじゃない人が突然swift-evolutionに追加してたからよくわからなかったんだけどその関係で消された??
Avatar
前に Int(string)string.toInt() より優れているのは型が明確だという話があったけど( Swift.Int 以外の Int があっても区別できる)、一方で左に戻って書くのは面倒なときがあって => があれば string => Int.init ができるという話で、いくらなんでも => は可読性が悪いので、ふと思いついて↓を作ってみた。 let s = "42" // instead of `Int(s)` let a: Int? = s.to(Int.self) https://github.com/koher/righto
Contribute to righto development by creating an account on GitHub.
Avatar
左辺値型推論にしたいけどメソッドチェーンとかオーバーロードの引数に渡す時が使いにくくなっちゃいますね to<Int>()ができればいろいろよさげなのに
2:16 AM
ジェネリックにできないからこれもだめなのかな
Avatar
omochimetaru 8/28/2017 2:18 AM
protocol FromA があれば A.to<B: FromA>() -> B でジェネリックにはできるんじゃない?
Avatar
それがたくさん生えすぎるなぁと
Avatar
omochimetaru 8/28/2017 2:19 AM
@koher の ↑ righto はたくさん生えてるよ
Avatar
swift4のNumricで数値周りは整理されるんで楽になりそうだなぁとおもっていますが
Avatar
omochimetaru 8/28/2017 2:19 AM
そもそもが変換用イニシャライザだからたくさん生えてるし。
Avatar
それはそうなんですがw
Avatar
omochimetaru 8/28/2017 2:19 AM
負担は変わってないと思う
2:19 AM
いや、少し楽になるんじゃない?
2:20 AM
Swiftの明示的型パラが無いのは悩ましいよね
2:20 AM
返り値推論が取り回しづらい場合にそなえて f(type: T.Type) を取るパターンが多いけど
2:21 AM
typeを引数取るべきか返り値推論に頼るべきかの設計上のコンベンションがよくわからない
2:21 AM
みなさんどうしてるのかな
Avatar
func f<T>(type: T.Type=T.self)->T こう
Avatar
omochimetaru 8/28/2017 2:30 AM
そんなんできんの
Avatar
左辺の型で推論できるなら省略可能
2:31 AM
推論できないときは引数に入れる。便利よ
Avatar
omochimetaru 8/28/2017 2:31 AM
func f0<T>(type: T.Type = T.self) -> T? { return nil } let a: Int = f0() ?? 0 let b = f0(type: Int.self)
2:32 AM
ほ、ほんとだ、できた・・・
Avatar
righttoだと分かりにくいのが問題になりそう
Avatar
omochimetaru 8/28/2017 2:33 AM
convert(to: ) とかのほうがいいかもね
2:33 AM
でもとりあえずこれでrighttoの引数が推論省略可能にできるな
2:33 AM
そこまでいくと変換コンストラクタより圧倒的にいいな・・・
2:34 AM
Swift std の public func unsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U とかデフォルト引数ついてないから
2:34 AM
推論した後でデフォルト式の評価できると思ってなかったわ
2:34 AM
知見が深い
Avatar
RxSwiftのSharedSequenceで使われているテクニックだベ
2:37 AM
ほんとだ
2:38 AM
じゃあSwiftに明示的型パラが無くても末尾引数に = T.self つけとけば
2:38 AM
一般論として明示可能になるのか・・・
Avatar
そうだな
Avatar
T.Type=T.selfのテクニック、結構有用だしstdlibでも使って欲しいだけどevolutionかな
Avatar
class Base : ExpressibleByArrayLiteral { required init(arrayLiteral: Int...) { } } class Sub : Base { } let _: Sub = [1,2,3] なんとランタイムエラー fatal error: use of unimplemented initializer 'init(arrayLiteral:)' for class
Avatar
やっぱ class は複雑すぎるので廃止しよう😇
Avatar
variadic 引数を含む initializer は自動継承できないっていう制限なんだけど、TypeCheckerがそれを認識できてないですね。
Avatar
なるほど。
Avatar
omochimetaru 8/29/2017 5:52 AM
なんで可変長だと自動継承できないんだ・・?
5:52 AM
その制限要るのかな・・・ (edited)
Avatar
initializer の自動継承は、実際には サブクラスに initializer を synthesize して super.init を呼び出しているのですが (edited)
Avatar
omochimetaru 8/29/2017 5:53 AM
あ〜!!
5:53 AM
なるほど。
5:54 AM
super.initを呼び出すところでコーリングコンベンション的に困ったことになりますね
Avatar
AST で variadic 引数への splat を表現できないのです 😢
Avatar
omochimetaru 8/29/2017 5:55 AM
ああ、型システム的にもすでにArray化されちゃってるから、構文的には可変長引数へのspreadが必要なんですね。
Avatar
omochimetaru 8/29/2017 5:58 AM
2月だ
Avatar
なるほど・・・。構文は後回しにして spread のASTノードだけ先に作るとかでもいい気も。
Avatar
omochimetaru 8/29/2017 6:11 AM
ASTノードだけ先に作っても実際の呼び出しのところが問題になるのでは
Avatar
自動生成はできのでは?
Avatar
omochimetaru 8/29/2017 6:12 AM
あ、違うのか?Swift的には呼び出し側で配列を作ってるのかな
Avatar
AST で variadic 引数への splat を表現できないのです
Avatar
omochimetaru 8/29/2017 6:12 AM
C言語仕様の可変長引数呼び出しにした上で、自動生成されたサンク関数で配列につめてから、実装を呼んでるのかと思ったけど
6:13 AM
そもそもが見た目だけの問題でSwift上では配列でパッシングしてるなら、ASTだけの問題ですね
6:17 AM
func f0(_ xs: Int...) { } f0(11,22,33,44)
6:18 AM
// f0(_:) sil hidden @_T01a2f0ySaySiGd_tF : $@convention(thin) (@owned Array<Int>) -> () { // %0 // users: %2, %1 bb0(%0 : $Array<Int>): debug_value %0 : $Array<Int>, let, name "xs", argno 1 // id: %1 release_value %0 : $Array<Int> // id: %2 %3 = tuple () // user: %4 return %3 : $() // id: %4 } // end sil function '_T01a2f0ySaySiGd_tF'
6:18 AM
普通にArrayだった。
Avatar
とはいえ、その spread の ASTノードに対応した SILGen 対応は必要ですけどね。
Avatar
omochimetaru 8/29/2017 8:15 AM
最近まで Array.forEach は存在しないほうが良いと思ってて for in でできるだけ書いていたんですけど よくよく考えてみれば、 for in 文は break continue return などの様々な制御命令が含まれる可能性があるので、読み手がそれに注意しないとフローを読み解けないのに対して、 .forEach はそれらの制御ができないから、 .forEach で書きたいことが書ける場合にはできるだけ .forEach を使ったほうが 読み手に優しいため望ましい と思い始めたんだけどどうだろう
Avatar
let aa = [(0, 1)] for (a, (b, c)) in aa.enumerated() { } // aa.forEach { a, (b, c) in // 不可 // // } という特殊例 (edited)
8:19 AM
書いてて初めてforだとdestructuring assignmentできることに気付きました
Avatar
omochimetaru 8/29/2017 8:22 AM
3> aa.enumerated().forEach { (a, bc) in 4. let (b, c) = bc 5. print(a, b, c) 6. } こうしなきゃいけないのか
8:22 AM
最近見直されてるやつ
Avatar
一重タプルができてただけで二重以上のタプルはもともとできませんでしたね。
Avatar
omochimetaru 8/29/2017 8:24 AM
あ、そうなのか。
Avatar
forEach はイテレーション毎に関数呼び出しが入るから、 -Onone 時に遅そう。
Avatar
omochimetaru 8/29/2017 8:30 AM
それを言っちゃうと .map とかも for + var array: [Int] + array.append() にせよ、って話しになりそう。
Avatar
ごもっとも
Avatar
omochimetaru 8/29/2017 8:32 AM
最近 -Onone が遅くて困ってそれを実際にやった・・・ removeAll(keepCapacity: true) は良いぞ
Avatar
forEach はシンタックスハイライト上の問題で見づらいのと、 breakcontinue があるかはシンタックスハイライトでひと目でわかる(逆にわからないほどの巨大スコープを書くべきでない)ので for でいいんじゃないかなぁ。後から break なくなったから forEach に書き換えようとか逆も辛い・・・。
8:39 AM
Trailing Closure 使ったら制御構文のようにシンタックスハイライトされるなら話は別。
Avatar
逆にあとからフィルタ追加したい時、 foreach だから filter にしとこう->for+continueより効率悪とかもあるかも? (edited)
Avatar
omochimetaru 8/29/2017 8:41 AM
breakしたい時も可能ならば prefix(where) を使って
Avatar
filter みたいに戻り値が必要なケースはまた別では?
Avatar
omochimetaru 8/29/2017 8:41 AM
continueしたい時も可能ならば filterを使う。
Avatar
filter+foreach < for+continueって話です
Avatar
omochimetaru 8/29/2017 8:42 AM
「後からbreakしたくなるかもしれない」なものと、「後からbreakしたくはならなさそう」なものがあると思う。 (edited)
8:42 AM
そういう見通しの違いが表せるかなあと
8:42 AM
あと、「ひと目でわかる」より「全く見なくてもわかる」ほうが望ましい。
8:43 AM
for だけピンクで目立つけど forEach だと他のメソッドと同じように紫に見えてしまうっていうのは確かにデメリットですね (edited)
Avatar
for in 使わずに map, filterforEach ばっかでコード書くってのは昔試して、可読性悪すぎて死んだので個人的にやりたいとは思わないです。
8:44 AM
で、主な原因はシンタックスハイライトの違いという結論に落ち着いた。
8:44 AM
制御構文はまさに制御のためのもので、コードの制御構造を表していて、それがハイライトされて可視化されてるのは大きい。
Avatar
omochimetaru 8/29/2017 8:45 AM
うーんそうなのか
Avatar
で、大体の Trailing Closure は制御のためのものだと思うから、 Trailing Closure を同じようにハイライトしてくれれば全然違うんじゃないかと思ってる。
Avatar
omochimetaru 8/29/2017 8:45 AM
でもその制御が特定のパターンの場合に map みたいな名前がつけられるわけで
Avatar
逆にfor in 普段つかわない
Avatar
けど、そういうものを見たことがないから確証はない。
Avatar
omochimetaru 8/29/2017 8:46 AM
全部読み解くより map とか filter で表せるときはそっちを使ったほうが、意図が明確なコードになりそう。
Avatar
mapfilter は使い方によっては読みやすいし、使うよ。 forEach はほぼ使わない。
8:47 AM
forEach(foo) とできるときか、長くても forEach { foo($0) } みたいなときで
8:47 AM
すべての要素に対してこれを実行したいという意図が強いときかなぁ。
Avatar
omochimetaru 8/29/2017 8:47 AM
@hiragram その理由は?俺が言ったのと同じ?
8:47 AM
forEach はほぼ使わない。
ほぼでいうと、僕は、絶対に使わない主義だったんで
8:48 AM
僕の「使えるときは使っていく」が、 @koher の 「ほぼ使わない」よりも、たくさん使う状態なのかどうかはまだわからない
8:48 AM
すべての要素に対してこれを実行したいという意図が強いとき
イメージとしてはこれですね
Avatar
mapfilterlet ys = xs.map { foo($0) }.filter { bar($0) } くらいの感じなら連ねて書くし、
Avatar
omochimetaru 8/29/2017 8:48 AM
breakがあとから入れたくなりそうなときはそもそも制御を意識していると思う。
Avatar
おもちの理由どれだ
Avatar
omochimetaru 8/29/2017 8:50 AM
17:15のやつ (edited)
Avatar
クロージャ式の中身が複数行になったり、メソッドチェーンが長くなったりするときは式を区切って変数に代入して名前を付ける。
8:50 AM
それで、何のための処理かと、型が一目瞭然になるので可読性が高まる。
8:51 AM
特に、 mapflatMap の後は型を明示的に記述しておいた方が読みやすい。
Avatar
omochimetaru 8/29/2017 8:51 AM
それはそうですね
Avatar
だいたい同じ 最近まで Array.forEach は存在しないほうが良いと思ってて for in でできるだけ書いていたんですけど よくよく考えてみれば、 for in 文は break continue return などの様々な制御命令が含まれる可能性があるので、読み手がそれに注意しないとフローを読み解けないのに対して、 .forEach はそれらの制御ができないから、 .forEach で書きたいことが書ける場合にはできるだけ .forEach を使ったほうが 読み手に優しいため望ましい と思い始めたんだけどどうだろう
8:52 AM
forEachはそのブロックが全ての要素に対して1回実行されることだけ考えればいい(forEachの外にある変数触ってたりすると別だけどそれはやらないようにしてるから問題なし)
Avatar
.forEach で書きたいことが書ける場合
これって、 breakcontinue, return 等を含まないとき全部では?
Avatar
omochimetaru 8/29/2017 8:54 AM
その時含んでいないかというより、後にも含みそうにないか、ですね
Avatar
僕の「使えるときは使っていく」が、 @koher の 「ほぼ使わない」よりも、たくさん使う状態なのかどうかはまだわからない
使えるときはすべて使っていこうという積極的な姿勢に思えたけどそうではない?
8:55 AM
5 行も 6 行も処理が書かれたクロージャ式自体が(特に制御目的だと)微妙な気がしてる。
Avatar
omochimetaru 8/29/2017 8:55 AM
あーどうなんだろう、長い時こそ forEachの優位性が高まる気もする・・・
8:56 AM
そもそも長くするなというのはある。
Avatar
continue は forEach だと return で代用「できちゃう」から、視認コスト的には大して変化しないんじゃないか。
Avatar
omochimetaru 8/29/2017 8:56 AM
ああそうか。
8:56 AM
違うのは breakreturn だけですね。
8:57 AM
for 内部に continue があるかどうか見なきゃいけないのと forEachに return があるかどうか見なきゃいけないのは同じだ
Avatar
forEachreturn はトラップになりそうだ・・・。
Avatar
as, as?, as! をoperatorにしよう」という話があるらしい。 (edited)
12:39 AM
キャストの挙動をそれぞれの型で定義できる様に。
Avatar
ユーザー定義ってことですか?
Avatar
そそ
Avatar
もしそうなったら、castやtoIntなどではなく
12:44 AM
as対応として変換を提供する選択肢も出て来ますね
Avatar
興味深い
12:55 AM
asが定義できるとして、暗黙になるかどうかは議論がありそう
Avatar
Optionalの変換とか、asde
1:17 AM
asで定義されていることになって、ユーザ側でもそういうの追加できるようになると良いな。
Avatar
subscript のオーバーロードってSwift3だとambiguosになるんですね…… swift4だと治ってるようなのでそれ待ちか
Avatar
ジェネリックと型固定がある場合か。
Avatar
norio_nomura 9/1/2017 12:52 AM
これは4.1に入るのだろうか? https://twitter.com/olebegemann/status/903362839380975619
Coming soon to a Swift compiler near you! 😂 (Thanks @CodaFi_ for implementing an old proposal, accepted May 2016!) https://t.co/D4jP5eaGUJ
Avatar
#if os(macOS)とかよりは良いですね
12:54 AM
watchOSとかtvOSとかはどうすればいいのかわからないことが多いので
Avatar
canImportめっちゃよい
1:02 AM
良さ高い
Avatar
omochimetaru 9/1/2017 1:23 AM
おーこれは良いね
Avatar
#if canImport(WebKit)とかもできるだろうか
2:03 AM
少し違いそう
2:03 AM
なんかコレコレimportしたらこの機能が追加される〜みたいなのが欲しいという話
Avatar
これってサードパーティのフレームワークも OK ?
2:11 AM
それなら、前に話してた、パッケージを細かく分割して、
2:11 AM
でも AB を同時に使う場合だけの extension を足したいみたいなのも実現できそう。
Avatar
そうそう
2:12 AM
APIKit+RxSwiftでRxAPIKit入れるみたいなそう言う拡張が
2:12 AM
import RxAPIKitと書くのはしんどいなが解決できる可能性がある
Avatar
それができたら素晴らしい
Avatar
norio_nomura 9/1/2017 2:17 AM
テストを見る限り任意のモジュールでできそう https://github.com/apple/swift/pull/11613/files#diff-cef9f57a4c8714bfa701eabcd4c34730R7
This implementation required a compromise between parser performance and AST structuring. On the one hand, Parse must be fast in order to keep things in the IDE zippy, on the other we must hit the...
🙂 2
Avatar
おお〜
Avatar
omochimetaru 9/1/2017 2:41 AM
こういうの見ると、何でもinterpolateできるようにしたのはSwiftの設計ミスだよなーと思う。StringInterpolatableみたいなプロトコル必須にすればよかったのに。 https://t.co/dudcbIeIgG
2:41 AM
僕はSwiftの設計ミスというよりOptional型のdescriptionが良くなかっただけじゃないかなーという気がする
2:41 AM
@hiragram debug文字列の取得とinterpolationを同一視するのが間違いだったと思ってます。Javaでもこのあたりは同様なんですが、Javaは20年前の設計なのでなにもそれを真似する必要はなかった。
2:41 AM
@gfx @hiragram 本来はデバッグ用の表現より文字列用の表現が優先するんですが、Optional型だけはデバッグ用の表現を優先するみたいです https://t.co/MmfUmkuDN5 https://t.co/q4SMb1Lfvj
2:41 AM
@gfx @hiragram 優先度は TextOutputStreamable > CustomStringConvertible > CustomDebugStringConvertible > リフレクションによるダンプ
2:42 AM
@omochimetaru @hiragram 工エエェェ(´д`)ェェエエ工 _isOptional で分岐してるんですか…。なんということでしょう。
Avatar
"\(foo)"に関してはfooがCustomStringConvertibleじゃなければ遍く警告で良いと思うんだよな〜
Avatar
今ってOptionalだけ警告だっけ?
Avatar
omochimetaru 9/1/2017 2:51 AM
うん。
2:51 AM
print("\(Cat())") // "__lldb_expr_31.Cat\n" (edited)
2:55 AM
"(foo)"に関してはfooがCustomStringConvertibleじゃなければ遍く警告で良いと思うんだよな〜
たしかにこれはあるかも。 CustomDebugStringConvertible の結果がほしいときは、明示的に .debugDescription と書けと。
2:55 AM
CustomDebugStringConvertible もついてなくて、Mirrorの結果がほしいときは、 現状と同じく String(describing: expression) で良いしなあ
Avatar
swift-evolutionで提案して・・・
Avatar
omochimetaru 9/1/2017 2:56 AM
なんかわりと良い提案な感じがする
2:56 AM
なんか過去に議論されてた気がするんですよね
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 9/1/2017 2:57 AM
でもさっきevolutionちらっと見たときは見つけられなかった (edited)
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
2:57 AM
そういうときに Gmail 検索できるように全部受信しておくと便利
Avatar
途中から登録したら見付けられなくてしぬ
Avatar
omochimetaru 9/1/2017 2:58 AM
なんかもっと前は、 Optional でも警告無しで文字列化できていた
Avatar
そろそろevolution書いていかないとだ
Avatar
Swift 3.1からは警告指摘対象になって、こういうミスしにくくなった( ´・‿・`) https://t.co/RJ2CnFgqiK https://t.co/y84AjhJFlJ
Avatar
omochimetaru 9/1/2017 2:59 AM
SR-1882: 文字列補間(String interpolation)にOptional型を直接用いると警告が出るように
2:59 AM
SRってなんだっけ?SEはevolutionですよね
3:02 AM
コントリビューションガイド読んでみるかあ
Avatar
Swiftが名詞を関数/メソッド名にしてしまったことで変数名と衝突して困ることとかないですか?↓みたいにしたいときとか。 let foo = foo(from: ...)
Avatar
omochimetaru 9/1/2017 6:49 AM
右を self.foo にすればいけません?
Avatar
メソッドじゃなくて関数のときに困る・・・
Avatar
omochimetaru 9/1/2017 6:50 AM
ModuleName.foo
Avatar
ローカルな関数くらい getFoo 的な名前を付ければいいのかもだけど。
Avatar
この名前衝突するの結構前からありますけど解決しないんですかね?
Avatar
omochimetaru 9/1/2017 6:50 AM
あんまり関数は作らないからたまたま困ってなかった
Avatar
Foundation.stride使うときに変数をstrideにしておいて衝突するのがよくある
Avatar
omochimetaru 9/1/2017 6:51 AM
いや、いま func makeTranslation 作ってるな
Avatar
self. をつければいいというのも、本当にそれでいいのかというのもある。
Avatar
omochimetaru 9/1/2017 6:51 AM
これコンベンション間違いか
6:52 AM
左辺が var mat = だからギリセーフだけど
6:52 AM
ちゃんとやったら踏みそうな気がしてkチア
Avatar
let texturePaths = texturePaths(in: ...) ってやりたくて辛い目に・・・。
6:53 AM
左辺を texpaths とかにするのも考えたけど不細工だし・・・。
Avatar
omochimetaru 9/5/2017 3:51 AM
SourceKitten - An adorable little framework and command line tool for interacting with SourceKit.
3:52 AM
DispatchQueue.global(qos: .default).async { let registry = CommandRegistry<SourceKittenError>() registry.register(CompleteCommand()) registry.register(DocCommand()) registry.register(FormatCommand()) registry.register(IndexCommand()) registry.register(SyntaxCommand()) registry.register(StructureCommand()) registry.register(RequestCommand()) registry.register(VersionCommand()) registry.register(HelpCommand(registry: registry)) registry.main(defaultVerb: "help") { error in fputs("\(error)\n", stderr) } } dispatchMain()
3:52 AM
dispatchMain()  って関数に突入させれば
3:52 AM
DispatchQueueのメインループを最上位に持つプロセス作れるんだね
Avatar
sourcekitd_set_notification_handler() set the handler to be executed on main thread queue. So, we vacate main thread to dispatch_main().
Avatar
omochimetaru 9/5/2017 3:57 AM
その前のコミットだと、CommandantのCommand.mainに突入するだけだったのが
3:57 AM
dispatchMainの中で改めてCommand.mainに入るようになってますね
3:57 AM
Carthage - A simple, decentralized dependency manager for Cocoa
3:58 AM
CarthageのmainはCommand.mainに突入するだけ
3:58 AM
Command.mainはまっすぐ進むだけで特にRunLoopとかも構築してないけど
3:59 AM
Carthage内部での並列処理とかどうやってんだろう
3:59 AM
コマンドレベルでのプロセス切り離しと待機しかしてないのかな。
Avatar
ReactiveSwiftが入ってるからそっち側で何かあるのかな
Avatar
omochimetaru 9/5/2017 4:00 AM
ReactiveSwift側でdispatchQueueでバックグラウンドに投げることはできたとして
4:00 AM
メインにキューが無いとmainQueueに戻せないから
4:01 AM
疑似メイン+BGみたいな構成になりそう
4:01 AM
@available(OSX 10.6, *) public func dispatchMain() -> Never
4:01 AM
当然だけどNever
Avatar
norio_nomura 9/5/2017 4:07 AM
お?
Avatar
omochimetaru 9/5/2017 4:07 AM
dispatchMain 知らなかったけどこれは良いものを知った
Avatar
norio_nomura 9/5/2017 4:09 AM
sourcekitd_set_notification_handler を使うのに必要でした。
Avatar
omochimetaru 9/5/2017 4:10 AM
/// Lazily and singly computed Void constants to initialize SourceKit once per session. private let initializeSourceKit: Void = { sourcekitd_initialize() }() private let initializeSourceKitFailable: Void = { initializeSourceKit sourcekitd_set_notification_handler { response in if !sourcekitd_response_is_error(response!) { fflush(stdout) fputs("sourcekitten: connection to SourceKitService restored!\n", stderr) sourceKitWaitingRestoredSemaphore.signal() } sourcekitd_response_dispose(response!) } }()
⬆ 1
4:10 AM
グローバル変数のletをVoid型に宣言してlazy関数にしてる・・・
Avatar
norio_nomura 9/5/2017 4:12 AM
initializeSourceKitはjpsimが書き直してたはず
4:13 AM
CarthageはGCDで色々並列化していたはず。
Avatar
omochimetaru 9/5/2017 4:13 AM
なるほど
Avatar
norio_nomura 9/5/2017 4:16 AM
ReactiveCocoa(後のReactiveSwift)で複数スレッドの終了待ち通知を組んでたけど、通知時点のコールスタックが深すぎて、メインスレッドが終了する前に通知したスレッドが終了しきれずにクラッシュする不具合を直したことがある。
Avatar
norio_nomura 9/5/2017 4:26 AM
Carthage - A simple, decentralized dependency manager for Cocoa
Avatar
norio_nomura 9/5/2017 4:36 AM
ReactiveCocoaで通知してdispatch_groupで終了を待つ https://github.com/Carthage/ReactiveTask/blob/master/Sources/Task.swift#L44-L46
ReactiveTask - Flexible, stream-based abstraction for launching processes
Avatar
omochimetaru 9/5/2017 4:40 AM
おー
4:41 AM
ややこしい感じになってますね
Avatar
↓のメソッドって encoding.utf8 で失敗することってあるんでしょうか?おそらく、表現できない文字が含まれていたときに nil になるんでしょうが、 Swift の String の文字列の内部表現が UTF-16 なので、 encoding.utf8 なら Unicode のコードポイントの表現の変換だけだから失敗することがないように思います。 https://developer.apple.com/documentation/swift/stringprotocol/2923420-data
3:42 AM
あー、 String は内部表現が UTF-16 だけど、 StringProtocol はその限りではないか。
3:42 AM
↑は、 Stringdata(...) を呼ぶとして、 .utf8 で失敗し得るか。今、 ! を付けたい。 (edited)
Avatar
StringProtocolvar utf8: Self.UTF8View を必須としているので、なんらかのUTF8表現は返すことは保証されていますね。
3:50 AM
associatedtype UTF8View : Collection where Self.UTF8View.Element == UInt8
3:52 AM
けど、このメソッドは単純に ObjC Foundation にフォワードしているので、
Avatar
おお、ほんとですね。
3:52 AM
じゃあ StringProtocol であっても
Avatar
Foundation 実装次第ではあります。
Avatar
foo.data(using: .utf8) が失敗することはなさそうですね。
3:55 AM
ええっ・・・、これって Foundation 依存なんですね・・・。 String.Encoding が Foundation なのおどろきです・・・。 https://developer.apple.com/documentation/foundation/string.encoding (edited)
3:56 AM
Swift パッケージは閉じていない??🤔
3:57 AM
↑の .utf8 の変換自体は、現実的には失敗は考慮しなくていいでしょうが。それとは別の話題として Swift パッケージは何にも依存していないと思ってました。
3:58 AM
1> let a: String.Encoding = .utf8 error: repl.swift:1:15: error: 'Encoding' is not a member type of 'String' let a: String.Encoding = .utf8 ~~~~~~ ^ 1> import Foundation 2> let a: String.Encoding = .utf8 a: String.Encoding = { rawValue = 4 }
3:59 AM
iya
3:59 AM
いや、あたりまえか
3:59 AM
そもそも Data
3:59 AM
Foundation だから。
4:00 AM
謎なのは↓が Foundation じゃなくて Swift 下に書かれていることか。 https://developer.apple.com/documentation/swift/stringprotocol/2923420-data (edited)
4:01 AM
ん?おかしいのは URL だけ?
Avatar
ああ、とりあえず大丈夫そうです。流れとしては、 1. StringProtocol 2. String.CharacterView(str) で CharacterView に変換 3. String(charView) で String に変換 4. _bridgeToObjectiveC() で NSString に変換 5. data(using:)
🙏 1
4:02 AM
最悪のケースですね。実際には普通の String の場合はショートカットあります。
Avatar
ページ上部のパスはちゃんと Foundation になってました。 URL はその型の元のパッケージに依存するってことですかね・・・。
4:03 AM
@rintaro ありがとうございます!
Avatar
Data(str.utf8) は遅いかもしれないけど Swift の Foundation オーバーレイに閉じてて Objective-C に一切渡らず non-failable。
Avatar
omochimetaru 9/7/2017 1:33 AM
Awesome new Swift formatting live demo using libSyntax by @harlanhaskins !!! #tryswiftnyc
1:35 AM
swift - The Swift Programming Language
1:36 AM
swift - The Swift Programming Language
1:38 AM
swift - The Swift Programming Language
1:40 AM
swift - The Swift Programming Language
Avatar
SwiftPM版がほしい。
Avatar
omochimetaru 9/7/2017 1:43 AM
↑のツイートで @inamiy さんに聞いたところ公式もいろいろやる気っぽいけど、とりあえず使えたら楽しそうだからまとめてみようかなと思ってる
1:44 AM
現状の実装がめちゃくちゃ微妙で、 libSwiftSyntax.dylib が配置されてるところからの相対パス ../../../bin/swiftc を叩くので (ちなみにここで #dsohandle というマニアックな言語機能が使われている )
1:44 AM
普通にシステムの swiftc を叩くようにしたら良さそうと思ってる
1:44 AM
でも多分そこで SwiftSyntax と swiftc のバージョン互換性問題が出るw
Avatar
omochimetaru 9/7/2017 3:48 AM
SPMが .swiftを自動でみつけてコンパイルしてくれるように、 .swift.gyb をみつけたら自動でやってほしいのう
4:28 AM
とりあえずパッケージ化して $ which -a swiftc に対応させてみたんだけど
4:28 AM
swiftc -emit-syntax っていう機能が Xcode9 beta6 同梱版にはついてなくて
4:28 AM
動かなかった・・・
4:29 AM
SwiftSyntaxのコード自体は特に変わった依存先も無くて普通にコンパイルできた。
4:33 AM
うーん、どうしよ。
4:34 AM
xcode9beta7とかでふってこねえかな
Avatar
omochimetaru 9/7/2017 4:49 AM
自前ビルドしたswiftcの管理ってどうやるのが主流なんでしょう xcodeの中でツールキットを切り替えるやつを前提に考えるのが良いのかな
Avatar
omochimetaru 9/7/2017 5:15 AM
ツールチェーンビルド build-script -R だと、前述したとおり Xcode にインストールできるパッケージにはなりません。 Xcode にインストールするには、ツールチェーンというものをビルドしなければならないのですが、一番簡単な方法は、 utils/build-toolchain スクリプトを使用する事です。
5:15 AM
Swift がオープンソースになってしばらく経ちます。 コンパイラや標準ライブラリの開発に手を出してみたいけど、リポジトリを落とした後どうしていいかわからない!という方のために、まずは開発環境の構築方法をご紹介します。基本的には[RE...
5:15 AM
これか
5:16 AM
あ、スナップショットはDLできるんだった
Avatar
omochimetaru 9/7/2017 5:53 AM
Swift4.0ブランチの09/07スナップショットには入ってないけど無印の方の09/07には入ってた
5:53 AM
そういうこともあるのか・・・
Avatar
4.0 には載らない機能ということですね。
Avatar
omochimetaru 9/7/2017 5:54 AM
無印のほうって、4.0より先を見てるってことですか?
Avatar
はい、無印は master なので。
Avatar
omochimetaru 9/7/2017 5:55 AM
なるほど。
5:55 AM
Xcode無印は3系を配布しててbetaが4系だから、 4.0系のブランチのほうが先をみてるほうかと思っっていました
Avatar
omochimetaru 9/7/2017 6:18 AM
swift - The Swift Programming Language
6:18 AM
落として入れた swift-DEVELOPMENT-SNAPSHOT-2017-09-06-a-osx.pkg からだと -emit-syntax に対応していない
6:18 AM
何か見落としていそう・・・
Avatar
omochimetaru 9/7/2017 6:27 AM
あ!!!
6:27 AM
あ〜 やらかした
6:28 AM
[omochi@omochi-iMac bin]$ ./swiftc -frontend -emit-syntax <unknown>:0: error: this mode requires at least one input file
6:28 AM
いけそうになってきた
6:30 AM
xcode-selectで切り替えて $ swift に通るパスは、Xcode同梱のものにすぎなくて
6:31 AM
Xcodeがtoolchain設定でビルド時に使用するものを切り替える挙動は、 システムの $ swift を差し替えるわけではないんですね
6:31 AM
なんか前に @norio_nomura さんが書いてた・・・ 環境変数があったような・・・
Avatar
xcrun --toolchain swift で toolchain指定した swift 起動できません?一番それがお手軽かと。
Avatar
omochimetaru 9/7/2017 6:45 AM
あーーいけました ちょうど辿りつつあった。 https://github.com/apple/swift-package-manager/blob/master/README.md#managing-swift-environments SPMのとこにヒントが
swift-package-manager - The Package Manager for the Swift Programming Language
6:45 AM
--toolchain swift-latest とか --toolchain swift-DEVELOPMENT-SNAPSHOT-2017-09-06-a とか
6:45 AM
ためしてたんですが
6:45 AM
--toolchain swift ←なんで・・・
6:47 AM
$ xcrun --toolchain swift --find swift でいけそうです、ありがとうございます
6:52 AM
できた!!
6:52 AM
できたぞ〜〜
Avatar
omochimetaru 9/7/2017 7:02 AM
Contribute to SwiftSyntax development by creating an account on GitHub.
7:02 AM
import Foundation import SwiftSyntax func main() throws { let args = Array<String>(CommandLine.arguments.dropFirst()) if args.count < 1 { fatalError("not specified file") } let path = args[0] let source = try Syntax.parse(URL(fileURLWithPath: path)) print(source) } try main()
7:02 AM
↑パースしてプリントするだけの何もしないサンプルが動いた
7:03 AM
ASTに空白文字とかコメントの情報もくっついてるから
7:03 AM
テキストとしてパススルー
Avatar
README 見て一瞬 executable なのかと思ったらちゃんとパッケージになってた。
Avatar
omochimetaru 9/7/2017 7:05 AM
Library targetのほうが SwiftSyntax って名前になってる。
Avatar
ややこしいから executable なくてもいいかも?特にコマンドとして強化するわけじゃなかったら。
Avatar
omochimetaru 9/7/2017 7:05 AM
まあたしかに。
Avatar
testExample に入れとけば十分そう。
Avatar
omochimetaru 9/7/2017 7:06 AM
使用例を提示したいだけです
Avatar
↑の testExample は使用例の話ね。
7:08 AM
ライセンスは Swift に準ずることになるのかな? https://github.com/apple/swift/blob/master/LICENSE.txt
swift - The Swift Programming Language
Avatar
omochimetaru 9/7/2017 7:08 AM
そうですね
Avatar
omochimetaru 9/7/2017 7:37 AM
// comment import Foundation class Cat { var name: String = "mike" }
7:37 AM
[0] process type: SourceFileSyntax [1] process type: SyntaxCollection<DeclSyntax> [2] process type: UnknownDeclSyntax [3] process type: TokenSyntax text: import leading: Trivia(pieces: [// comment, ]) trailing: Trivia(pieces: [ ]) [3] process type: TokenSyntax text: Foundation leading: Trivia(pieces: []) trailing: Trivia(pieces: []) [2] process type: UnknownDeclSyntax [3] process type: TokenSyntax text: class leading: Trivia(pieces: [ ]) trailing: Trivia(pieces: [ ]) [3] process type: TokenSyntax text: Cat leading: Trivia(pieces: []) trailing: Trivia(pieces: [ ]) [3] process type: TokenSyntax text: { leading: Trivia(pieces: []) trailing: Trivia(pieces: []) [3] process type: TokenSyntax text: var leading: Trivia(pieces: [ , ]) trailing: Trivia(pieces: [ ]) [3] process type: TokenSyntax text: name leading: Trivia(pieces: []) trailing: Trivia(pieces: []) [3] process type: TokenSyntax text: : leading: Trivia(pieces: []) trailing: Trivia(pieces: [ ]) [3] process type: TokenSyntax text: String leading: Trivia(pieces: []) trailing: Trivia(pieces: [ ]) [3] process type: TokenSyntax text: = leading: Trivia(pieces: []) trailing: Trivia(pieces: [ ]) [3] process type: TokenSyntax text: "mike" leading: Trivia(pieces: []) trailing: Trivia(pieces: []) [3] process type: TokenSyntax text: } leading: Trivia(pieces: [ ]) trailing: Trivia(pieces: []) [1] process type: TokenSyntax text: leading: Trivia(pieces: [ ]) trailing: Trivia(pieces: [])
7:38 AM
トークンに対して leadingTrivia と trailingTrivia として、コメントとかスペースとか、意味のない系の文字列がついてくる
7:39 AM
TriviaはTriviaPieceの配列で、TriviaPieceは 空白とか行コメントとかブロックコメントみたいな単位で型付けされてる(enum)
7:39 AM
使いやすそうな雰囲気
Avatar
omochimetaru 9/7/2017 7:52 AM
TypealaisDeclやStructDeclはあるのにImportDeclやClassDeclはなくてUnknownDeclとやらになる・・・
Avatar
TypealaisDeclやStructDeclはあるのにImportDeclやClassDeclはなくてUnknownDeclとやらになる・・・
未対応ってことですー。
Avatar
omochimetaru 9/7/2017 9:22 AM
なるほど
Avatar
omochimetaru 9/7/2017 11:09 AM
class DefaultCat { var name: String = "mike" } // yahho @objc public class PublicCat {}
11:10 AM
$ swift run format-example Resources/a.swift
11:10 AM
fileprivate class DefaultCat { var name: String = "mike" } // yahho @objc fileprivate public PublicCat {}
11:10 AM
↑試しにクラス定義に fileprivate をつけるプログラムを書いてみた。
Avatar
norio_nomura 9/7/2017 12:20 PM
xcrunを使うとmacOSでしか動かないよ。
🙏 1
Avatar
omochimetaru 9/7/2017 1:03 PM
あ、なるほど。 https://github.com/omochi/SwiftSyntax/blob/master/Sources/SwiftSyntax/SwiftcInvocation.swift#L152 ここの中身だけ #if したほうがよさそうですね (edited)
Contribute to SwiftSyntax development by creating an account on GitHub.
1:04 PM
もともとの実装に対して swiftc の探索を追加しているだけなので、空にしたらよさそう。
Avatar
norio_nomura 9/7/2017 11:39 PM
macOSにおいては環境変数TOOLCHAINSを設定して使った方が良いかと。
Avatar
omochimetaru 9/8/2017 2:21 AM
あーそうですね SPMもそうだし、そのほうが切り替えが効くか・・・
2:23 AM
ところでどういうルールにもとづいて
2:23 AM
TOOLCHAINS=swiftにしたときに
2:24 AM
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain から /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2017-09-06-a.xctoolchain に切り替わるんですか?
2:24 AM
TOOLCHAINS=swift-DEVELOPMENT-SNAPSHOT-2017-09-06-a とかなら理解できるんですが
Avatar
omochimetaru 9/8/2017 4:12 AM
protocol P0 {} extension Array where Element : P0 { func aaa() {} } var xs = Array<P0>() xs.aaa() // error: using 'P0' as a concrete type conforming to protocol 'P0' is not supported
🤔 1
4:13 AM
protocol P0 {} extension Array where Element : P0 { func aaa() {} } extension Array where Element == P0 { func aaa() {} } var xs = Array<P0>() xs.aaa() // compile ok
🤔 2
Avatar
ディスパッチの問題とかですかね? where Element: P0 の場合は Array<P0> とは限らないので静的ディスパッチできないとか
Avatar
omochimetaru 9/8/2017 4:20 AM
Element: P0 が Array<P0> として扱えないのはまあわかるんですが、逆方向の Array<P0> が Element : P0 として扱えても良いと思う
4:20 AM
concrete typeとして使う時のprotocolって、ようはコンパイラが自動生成した AnyP0 と同じ機能をもつと思うので。
Avatar
protocol P0 { } struct Type: P0 { } extension Array where Element: P0 { func test() { print("P0") } } extension Array where Element == Type { func test() { print("Type") } } let type = Array<Type>() type.test() // Type let p0 = Array<P0>() p0.test() /* iOSPlayground.playground:9:7: note: found this candidate func test() { ^ iOSPlayground.playground:15:7: note: found this candidate func test() { ^ */
🤔 2
Avatar
omochimetaru 9/8/2017 4:23 AM
それ曖昧なのか・・・
4:24 AM
ええ?なんで?w
Avatar
何でやp0の時Type関係ないやろ
Avatar
omochimetaru 9/8/2017 4:24 AM
どう考えても片方しかマッチしないやろ
Avatar
protocolをgenericsに入れるの、この手の不可解な動きが多すぎるので
4:44 AM
@objc protocol以外は絶対に入れないようにしてる
Avatar
omochimetaru 9/8/2017 7:16 AM
DebugReflect - Debug dump support for Swift
7:16 AM
デバッグダンプ用のライブラリを作ったんだけど
7:18 AM
このような方法で、 https://github.com/omochi/DebugReflect/blob/master/Sources/DebugReflect/Util.swift#L25 Anyやconcrete protocolが保持している値が struct なのか class なのか判定できる事がわかったんで、 こうやってクラスに関して循環訪問するのをふせいでる https://github.com/omochi/DebugReflect/blob/master/Sources/DebugReflect/DebugReflectWriter.swift#L21-L27
DebugReflect - Debug dump support for Swift
DebugReflect - Debug dump support for Swift
7:20 AM
Any や Concrete Protocolは内部的には参照型のポインタ共有か、値型を保持するヒープ上のボックスへのポインタだから
7:20 AM
常に as AnyObject は 成功してしまうんだけど
7:20 AM
type (of: any) is AnyObject.Type だと判定できるのだ
Avatar
Mirrorとどっちがいいだろうか
Avatar
omochimetaru 9/8/2017 7:21 AM
命名の話? Swift標準の Mirror に乗っかる話?
Avatar
後者
Avatar
omochimetaru 9/8/2017 7:21 AM
後者だと、ツリー構造において weak var parent を無視したいとか
7:21 AM
そういうのでめんどくさそうなんだよね
Avatar
あーそっちの意味もあるか
7:22 AM
えっと
7:22 AM
type(of: any)のとこをMirrorで見分けることができるかなと
Avatar
omochimetaru 9/8/2017 7:22 AM
あ、そっちか
7:23 AM
できそうだけどMirrorは使わないで済むなら使わないほうがいいやつだと思う
7:24 AM
let subjectType: Any.Type
7:24 AM
結局このプロパティをみることになって Mirror(reflecting: x).subjectType と書くのと type(of: x) と書くのが同じ意味になりそう。
Avatar
ふむ
Avatar
ツリー構造において、親の存在はせいぜいn階層に対してnで爆発はしないから
7:44 AM
Mirror使った実装でいい気もしてきた
Avatar
omochimetaru 9/8/2017 7:46 AM
それはライブラリ自体の仕組みの話?
Avatar
sou
Avatar
omochimetaru 9/8/2017 7:46 AM
まあ現状でも
7:46 AM
デフォルトエクステンションとして
7:46 AM
Mirrorによる実装を注入しておくとかは
7:46 AM
可能なんだよね
7:46 AM
Mirror実装の振る舞いが困る人は手で実装すればいいって形にできる
Avatar
norio_nomura 9/8/2017 11:56 PM
TOOLCHAINS=swift-DEVELOPMENT-SNAPSHOT-2017-09-06-a とかなら理解できるんですが TOOLCHAINS=swiftは省略形で、複数バージョンのtoolchainがインストールされている場TOOLCHAINS=org.swift.3020170906aと書きます。 Xcode 7.3からかな? https://developer.apple.com/library/content/releasenotes/DeveloperTools/RN-Xcode/Chapters/Introduction.html#//apple_ref/doc/uid/TP40001051-CH1-SW233 To use an alternative toolchain with command-line tools, use `xcrun --toolchain swift` and `xcodebuild TOOLCHAINS=swift`. You can provide either the abbreviated or the full identifier for the toolchain, for example, `xcrun --toolchain swift` or `xcrun --toolchain org.swift.20151231a`.
🙏 1
11:59 PM
インストールされているtoolchainのidはインストーラパッケージのidにも使われているので、 $ pkgutil --pkgs|grep -i org.swift org.swift.3020170908a とかするとみつけられます。
12:02 AM
ちなみに/Library/Developer/Toolchains/ から削除してもパッケージデータベースには残るので、過去にインストールした分も出てくるかと思います。その場合 $ sudo pkgutil --forget org.swift.3020170908a Password: Forgot package 'org.swift.3020170908a' on '/'. でパッケージデータベースから削除できます。
Avatar
omochimetaru 9/10/2017 7:13 AM
なるほど!ファイル名じゃなくてpkgutil系のエントリが作られているんですね!
Avatar
identifier自体は/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2017-09-08-a.xctoolchain/Info.plistCFBundleIdentifierとして記述されているものをチェックしてるのだと思います。
Avatar
omochimetaru 9/11/2017 1:35 AM
本当だ。Aliasesとして swift とも指定されていますね。
Avatar
var foo: Bool { switch x { ... } } ↑こういうの、別にクラスの中だけじゃなくて、適当にその辺にも書けるんですね。funcも書けるから考えたら当たり前だけど認識の外にあったから使えてなかった。
Avatar
使えるけど使いたいとは思わない系のものですかね 🤔
Avatar
let foo: Bool switch x { case ...: foo = true case ...: foo = false ... } (edited)
6:58 AM
これとの比較ですが、ブロックにしまっちゃいたい感情
Avatar
それならどうせならクロージャーにまとめたい感情 let foo: Bool = { switch x { case ...: return true default: return false } }()
Avatar
クロージャだと補完が厳しいのと、直感に従えばコンパイル後はクロージャと同じになる気がしていて
Avatar
omochimetaru 9/13/2017 7:01 AM
run派 let foo: Bool = run { switch x { case ...: return true default: return false } }
Avatar
タイプ数の差も優秀
Avatar
でも let 使える
Avatar
見た目だけの違いで同じですよ
7:02 AM
var x { get } なので再代入不可能
Avatar
omochimetaru 9/13/2017 7:02 AM
たるのん式だと foo を3回書くのがね
Avatar
でも実行時によって値の変化の可能性あり
Avatar
omochimetaru 9/13/2017 7:03 AM
あ、var { get } にしたい元の書式の話か
7:03 AM
var { get } にすると都度計算されちゃうから同一値保証が無いね
Avatar
元のリソースを書き換えるのを考慮してなかった
7:04 AM
基本全部letで書いていきたいですね
Avatar
前出てた @_export、 vaporプロジェクトの redisモジュールで使われてる (edited)
11:11 AM
redis - ⚡️Pure Swift Redis client built on top of vapor/sockets.
11:11 AM
@_exported import Core @_exported import Node
11:12 AM
CoreとNodeは vapor/core と vapor/node https://github.com/vapor/redis/blob/master/Package.swift
redis - ⚡️Pure Swift Redis client built on top of vapor/sockets.
Avatar
omochimetaru 9/19/2017 7:25 AM
複数のSwift Toolchainがインストールされている時、Xcodeで使うやつを切り替えても、 xcrun --toolchain swift で使われるものはそれと連動して切り替わらないみたいなんですが、 Xcodeで指定してるツールチェインを取る方法について知りませんか? @norio_nomura
Avatar
norio_nomura 9/19/2017 7:29 AM
xcrun --toolchain swiftはどこで呼ばれるの?
Avatar
omochimetaru 9/19/2017 7:30 AM
Contribute to SwiftSyntax development by creating an account on GitHub.
7:30 AM
Apple通常配布版のSwiftだと -emit-syntax の機能が使えないから、swift org から落としてきたデイリースナップショットをインストールしてもらって、 SwiftSyntaxはそれを叩く必要がある
Avatar
norio_nomura 9/19/2017 7:44 AM
子プロセスを起動する時に環境変数TOOLCHAINSを引き継がないとダメじゃないかな?
Avatar
omochimetaru 9/19/2017 7:45 AM
あーそういう意味だとそもそも、普通に単体でシェルで xcrun --toolchain swift をやったときの結果も
7:46 AM
xcodeと連動していないので困っています
Avatar
xcrun --toolchain `defaults read com.apple.dt.Xcode DVTDefaultToolchainOverrideIdentifer` --find swift これが一番手っ取り早い気がする。
Avatar
omochimetaru 9/19/2017 7:46 AM
お、xcodeの設定が反映されてる。
Avatar
norio_nomura 9/19/2017 7:47 AM
そもそもSwift Package Managerからの起動で、XcodeがGUIで選択しているtoolchainは取得できないよね。
Avatar
omochimetaru 9/19/2017 7:47 AM
あー
7:48 AM
そうか、SPM開発においてはそもそも、TOOLCHAINSを設定するものか
Avatar
norio_nomura 9/19/2017 7:49 AM
そう。なので、環境変数TOOLCHAINSを子プロセスに引き継いだ上で、単純にswiftcを叩けば良いと思う。
7:49 AM
$ swiftc --version Apple Swift version 4.0 (swiftlang-900.0.65 clang-900.0.37) Target: x86_64-apple-macosx10.9 $ TOOLCHAINS=swift swiftc --version Apple Swift version 4.1-dev (LLVM 0ccf92e239, Clang f2b194a275, Swift 110c8437f9) Target: x86_64-apple-darwin17.0.0 (edited)
7:50 AM
xcrunなんて使う必要ない。
Avatar
omochimetaru 9/19/2017 7:51 AM
TOOLCHAINSの適用は普通のswiftコマンドでも自分で面倒みて切り替わってくれるんですね
7:51 AM
swiftコマンド自体がswiftコマンドをdispatchするの便利だな
7:51 AM
納得です、この流儀を前提に見直します。 @rintaro もありがとうございました。
Avatar
TOOLCHAINS 環境変数設定しても、Xcodeで選んだやつにならなくないですか?
Avatar
omochimetaru 9/19/2017 7:52 AM
Xcodeで選んだやつにするっていう発想が間違っていたと思いました
Avatar
norio_nomura 9/19/2017 7:52 AM
この場合、多分Xcodeで選ぶ必要はないのです
Avatar
古いdevelopmentスナップショット入っていると、そっちが選ばれてしまって
Avatar
norio_nomura 9/19/2017 7:53 AM
あ、Xcodeで実行する時は必要。
Avatar
-emit-syntax 無くて怒られる。 (edited)
Avatar
omochimetaru 9/19/2017 7:53 AM
export TOOLCHAINS=org.swift.3020170906a
7:53 AM
=swift だとだめなので、 ↑この形式のピンポイント指定ですね
Avatar
ピンポイント指定するしかないみたいですね。
Avatar
norio_nomura 9/19/2017 7:55 AM
XcodeのschemeのrunアクションにはTOOLCHAINSを指定して、ビルドに使うツールチェインにはスナップショット使う必要ないのでは。
7:56 AM
ああ、Swift Package ManagerでのビルドにはTOOLCHAINSを使うことで、4.0リリースと最新スナップショットの両対応テストのフローが出来るかな。 (edited)
8:02 AM
子プロセスを起動する時に環境変数TOOLCHAINSを引き継がないとダメじゃないかな? これは勝手に引き継がれるね。
8:04 AM
$ TOOLCHAINS=swift swift run format-example Package.swift Compile Swift Module 'SwiftSyntax' (16 sources) Linking ./.build/x86_64-apple-macosx10.10/debug/format-example -- debug -- [0] process type: SourceFileSyntax [1] process type: SyntaxCollection<DeclSyntax> [2] process type: UnknownDeclSyntax [3] process type: TokenSyntax text: import leading: Trivia(pieces: [// swift-tools-version:4.0, ]) trailing: Trivia(pieces: [ ]) [3] process type: TokenSyntax text: PackageDescription leading: Trivia(pieces: []) trailing: Trivia(pieces: []) [2] process type: TopLevelCodeDeclSyntax [3] process type: CodeBlockSyntax [1] process type: TokenSyntax text: leading: Trivia(pieces: [ ]) trailing: Trivia(pieces: [])
Avatar
omochimetaru 9/19/2017 8:06 AM
↑現在の実装だとxcrun --toolchain swift で見つけたものを使っちゃうのでテストにならないです
Avatar
norio_nomura 9/19/2017 8:07 AM
これではダメなの? $ TOOLCHAINS=swift xcrun --toolchain swift --find swiftc /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2017-09-18-a.xctoolchain/usr/bin/swiftc
Avatar
omochimetaru 9/19/2017 8:08 AM
むむ?
Avatar
norio_nomura 9/19/2017 8:12 AM
多分 Process に渡す swiftc を指す URL が必要なんだと思うけど、/usr/bin/which swiftcで返ってくる/usr/bin/swiftcをそのまま使えばいいんじゃないかな? $ /usr/bin/swiftc --version Apple Swift version 4.0 (swiftlang-900.0.65 clang-900.0.37) Target: x86_64-apple-macosx10.9 $ TOOLCHAINS=swift /usr/bin/swiftc --version Apple Swift version 4.1-dev (LLVM 0ccf92e239, Clang f2b194a275, Swift 110c8437f9) Target: x86_64-apple-darwin17.0.0 (edited)
Avatar
omochimetaru 9/19/2017 8:12 AM
ですね
8:12 AM
現状から locateXcrunSwiftc() を削除するだけっぽい
Avatar
norio_nomura 9/19/2017 8:14 AM
SPMでもXcodeでも環境変数TOOLCHAINSを使うのは避けられないと思うので。
8:16 AM
プロジェクトのビルドはSwift 4.0だけど-emit-syntaxは最新のスナップショットで、ってのが将来必要になるのならば、format-exampleコマンド自体に--toolchainオプションを持たせるとかしないとダメかな。 (edited)
Avatar
omochimetaru 9/19/2017 8:18 AM
まあその場合も TOOLCHAINS=org.swift.xxxx swift run format-example ... で
Avatar
norio_nomura 9/19/2017 8:18 AM
それだと最新のスナップショットでのビルドがswift runで走っちゃうよ。
Avatar
omochimetaru 9/19/2017 8:19 AM
あーそゆことか
Avatar
norio_nomura 9/19/2017 8:19 AM
ビルド済みモジュールのtoolchainバージョンと起動しているtoolchainのバージョンが違うと、リビルドされてしまうから。 (edited)
8:21 AM
swift-DEVELOPMENT-SNAPSHOT-2017-09-18-aはSwift 4.1を名乗るってことは、-emit-syntaxはSwift 4.1に入るのかな?
8:22 AM
だとすると4.0と最新スナップショットの違いに神経質になる必要はないのかも。
Avatar
omochimetaru 9/19/2017 8:23 AM
swift.orgでダウンロードできるやつだと
8:23 AM
Swift4.0branchのスナップショットもあって
8:23 AM
そっちだと駄目なんですよね (edited)
Avatar
swift - The Swift Programming Language
Avatar
norio_nomura 9/20/2017 2:10 AM
Swift 4 is now officially released! Swift 4 builds on the strengths of Swift 3, delivering greater robustness and stability, providing source code compatibility with Swift 3, making improvements to the standard library, and adding features like archival and serialization.
🎉 9
Avatar
[6/24] Generating C:/Users/qoncept/work/swift-build/build/./lib/swift/windows/x86_64/MSVCRT.swiftmodule FAILED: lib/swift/windows/x86_64/MSVCRT.swiftmodule lib/swift/windows/x86_64/MSVCRT.swiftdoc cmd.exe /C "cd /D C:\Users\qoncept\work\swift-build\build\stdlib\public\Platform && "C:\Program Files\CMake\bin\cmake.exe" -E remove -f C:/Users/qoncept/work/swift-build/build/./lib/swift/windows/x86_64/MSVCRT.swiftmodule && "C:\Program Files\CMake\bin\cmake.exe" -E remove -f C:/Users/qoncept/work/swift-build/build/./lib/swift/windows/x86_64/MSVCRT.swiftdoc && C:\Python27\python.exe C:/Users/qoncept/work/swift-build/swift/utils/line-directive @C:/Users/qoncept/work/swift-build/build/stdlib/public/Platform/fDmbf.txt -- C:/Users/qoncept/work/swift-build/build/./bin/swiftc -emit-module -o C:/Users/qoncept/work/swift-build/build/./lib/swift/windows/x86_64/MSVCRT.swiftmodule -target x86_64-unknown-windows-msvc -resource-dir C:/Users/qoncept/work/swift-build/build/./lib/swift -O -I C:/Users/qoncept/work/swift-build/build/./lib/swift/windows/x86_64 -module-cache-path C:/Users/qoncept/work/swift-build/build/./module-cache -no-link-objc-runtime -swift-version 3 -autolink-force-load -warn-swift3-objc-inference-complete -D_USRDLL -Fsystem //System/Library/PrivateFrameworks/ -Xfrontend -autolink-library -Xfrontend oldnames -Xfrontend -autolink-library -Xfrontend msvcrtd -module-link-name swiftMSVCRT -force-single-frontend-invocation -parse-as-library @C:/Users/qoncept/work/swift-build/build/stdlib/public/Platform/fDmbf.txt" C:/Users/qoncept/work/swift-build/swift/stdlib/public/Platform/msvcrt.swift:13:19: error: no such module 'ucrt' @_exported import ucrt // Clang module
12:27 PM
https://github.com/apple/swift/blob/master/docs/Windows.md を参考にWindowsでSwiftをビルドしようとしてるんですが、 MSVCRT.swidtmodule のビルドがうまくいかない
swift - The Swift Programming Language
12:29 PM
https://github.com/apple/swift/tree/master/stdlib/public/Platform msvcrt.swift, ucrt.modulemap, visualc.modulemap は同じディレクトリに入ってるけど、 modulemap から Framework とかを作らずにそもまま swift から import するのってできるんですっけ? (edited)
swift - The Swift Programming Language
Avatar
omochimetaru 9/20/2017 1:42 PM
コマンドラインで試してるけど、 -I オプションで渡したディレクトリ群の中に module.modulemap があると、 import できるようになる感じだなあ
1:44 PM
ucrt.modulemap を、module.modulemap にリネームした上で ライブラリのあるところにコピペして
1:44 PM
-I にパスを追加すればいいんだろうか
Avatar
omochimetaru 9/20/2017 8:40 PM
↑それで突破できました。
Avatar
WindowsネイティブでSwiftを使う動機が何なのか気になりました。
Avatar
iOS向けに実装したコードをwindowsで動かしたかった。
11:46 PM
bash on windowsでよかったんだけど
11:47 PM
特定のマシンでブルースクリーンが多発していて
11:47 PM
どうもHyperVが壊れている・・・
Avatar
あらら、なるほど。
Avatar
いろいろ弄ってかなりあと一歩まで来た
11:48 PM
[10/24] Linking CXX shared library bin\swiftSwiftPrivate.dll FAILED: bin/swiftSwiftPrivate.dll lib/swift/windows/i686/swiftSwiftPrivate.lib cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_dll --intdir=stdlib\private\SwiftPrivate\CMakeFiles\swiftSwiftPrivate-windows-i686.dir --manifests -- C:\PROGRA~2\MICROS~1.0\VC\bin\link.exe /nologo stdlib\private\SwiftPrivate\windows\i686\SwiftPrivate.obj /out:bin\swiftSwiftPrivate.dll /implib:lib\swift\windows\i686\swiftSwiftPrivate.lib /pdb:bin\swiftSwiftPrivate.pdb /dll /version:0.0 /machine:X86 /INCREMENTAL:NO -LIBPATH:C:/Users/omochi/work/swift-source/build/swift/./lib/swift/windows/i686 -LIBPATH:C:/Users/omochi/work/swift-source/build/swift/./bin/../lib/swift/windows/i686 -LIBPATH:C:/Users/omochi/work/swift-source/build/swift/./bin/../lib/swift/windows -LIBPATH:C:/Users/omochi/work/swift-source/icu/lib/icuuc.lib -LIBPATH:C:/Users/omochi/work/swift-source/icu/lib/icuin.lib -LIBPATH:C:\Users\omochi\work\swift-source\build\llvm\.\lib lib\swift\windows\i686\swiftCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ." ライブラリ lib\swift\windows\i686\swiftSwiftPrivate.lib とオブジェクト lib\swift\windows\i686\swiftSwiftPrivate.exp を作成中 SwiftPrivate.obj : error LNK2001: 外部シンボル "__T0s16TextOutputStreamMp" は未解決です。 bin\swiftSwiftPrivate.dll : fatal error LNK1120: 1 件の未解決の外部参照 LINK failed. with 1120
11:48 PM
Caveat Please note: this PR on its own does not constitute actual support for building on Windows upon merging this PR. For this, apple/swift-clang#45 and apple/swift-llvm#33 will have to be merged...
11:48 PM
↑このマージ済みのプルリクで
11:49 PM
_TMps16TextOutputStream のシンボルが見つからなくてlibSwiftPrivate.dllがビルドできない問題残ってるからこれはいつか直そう
11:49 PM
って書いてあるんですけど
11:49 PM
まさに今そこに到達した(Swift Manglingが少し変わって __T0s16TextOutputStreamMp だけど )
11:50 PM
ただこれが解決してるか誰かのパッチが転がってない限りここで詰みそう
11:55 PM
実際これかなり謎で、リンカ入力の lib\swift\windows\i686\swiftCore.lib をdumpbinで調べると、ちゃんと __T0s16TextOutputStreamMp は入ってるんですよね
Avatar
SwiftをWindowsでビルドするCIとか、誰か動かしてるのかな?
11:57 PM
無ければあっという間に壊れそうだ。
Avatar
手元でも、6/29のスナップショットに、masterと、未マージのパッチを個別に当てて
11:59 PM
やっとここまで来たので、めちゃ不安定だし
11:59 PM
そもそも先人がどこまで到達できているのか謎
11:59 PM
自分のステータスはswift.exeはビルドできるけど、stdlibはビルドできない、という状態で
12:00 AM
うーん。
12:02 AM
swift-windows - Swift for Windows (cygwin, msvc, mingw)
12:03 AM
Win nativeじゃなくてmingw環境だとこれが進んでますね
12:03 AM
リリースが今年の6月でとまってるけど (edited)
12:09 AM
こっちも試してみるか~・・・インストーラついてるみたいだし
Avatar
norio_nomura 9/21/2017 2:05 AM
swift-4.0-RELEASEswift-4.0-DEVELOPMENT-SNAPSHOT-2017-08-04-aへチェリーピックを足したものらしい。 $ git tag --merged swift-4.0-RELEASE|grep swift-4.0|tail -2 swift-4.0-DEVELOPMENT-SNAPSHOT-2017-08-04-a swift-4.0-RELEASE
Avatar
omochimetaru 9/21/2017 5:55 AM
Thanks for all your work helping to bring Swift to Windows. Do you plan to support building a DLL instead of an executable? This would help a lot for those of us interested in using Swift to write ...
5:56 AM
なるほど分割ビルドができない
Avatar
Swiftにコントリビュートする時の温度感を知りたい
2:43 AM
どこからevolutionでどこまでPRでいいのか、とか。
Avatar
新API追加はswift-evolutionだと思います。
2:44 AM
バグフィックスとかはPRでいいかと。
Avatar
tarunon - 2017/09/01 "\(foo)"に関してはfooがCustomStringConvertibleじゃなければ遍く警告で良いと思うんだよな〜
2:45 AM
これを試してうまく行ってる感あるので
Avatar
微妙ラインな気がしますね。
Avatar
ですよね
Avatar
PR投げてみて、swift-evolutionの方がよかったらProposal作るよ、みたいなコメント入れとくとか?
Avatar
なるほど
Avatar
@rintaro さんに聞いてみるのが一番よさそう・・・。
Avatar
りんたろさんたすけてくれ~~
Avatar
omochimetaru 9/22/2017 2:46 AM
プルリク見てると
Avatar
コミッターに投げる
Avatar
omochimetaru 9/22/2017 2:47 AM
それはswiftdevMLで話し合った方がいい みたいなレスがついて
2:47 AM
そのあとで、 いやこれはコアデザインだ、
2:47 AM
って別の人がレスしてるの
2:47 AM
きのうみた
Avatar
とりあえずPR投げてみて適切なところにForwardingしてもらうのが良いかしらね
Avatar
なるほど。それなら曖昧なものはとりあえず投げてみても良さそうな気も。
Avatar
幸いコードはあるから
Avatar
遅くなりました。evolutionになるにしても最早実装は必須なので、とりあえずPR投げちゃえばいいと思いますよ。
👀 1
🙂 1
Avatar
waiwai
3:13 AM
あざます
Avatar
omochimetaru 9/22/2017 3:50 AM
FileManagerのメソッドがだいたいStringなの気持ち悪い
3:50 AM
URLがいい
Avatar
てか Path 型がほしい。
Avatar
FileURLだと不足ですか?
🍰 1
Avatar
omochimetaru 9/22/2017 4:00 AM
自作のFilePath はよくつかってる
4:00 AM
あ、モアイさん復活した
Avatar
(ようやくdiscordみれました)
Avatar
omochimetaru 9/22/2017 4:01 AM
FileURL って URL型のコンストラクタですよね
4:01 AM
schemeとかportとか余計なプロパティがついてるから 型としてはちょっと広いんですよね
4:01 AM
Stringよりはマシですが
4:02 AM
ただ自作のファイルぶち込む可読性の低下と悩んでURLで我慢することもある
Avatar
たしかに内部では file:// で無理やりURLに当てて表現されてしまうのはありますね、完全に適してるかというと微妙なのはありそうですが
Avatar
omochimetaru 9/22/2017 4:03 AM
うっかりabsoluteStringつかうと file://ついてきたり。
Avatar
あるあるです
Avatar
omochimetaru 9/22/2017 4:03 AM
まあ、そのまま動くこともあるけどw
Avatar
↓こういうの辛い ((... as NSString).deletingLastPathComponent as NSString).appendingPathComponent(...)
Avatar
omochimetaru 9/22/2017 4:07 AM
なるべく早期にURL型にしておくと NS を見ないで済むw
Avatar
たまに URL から戻さないといけないときない?
Avatar
omochimetaru 9/22/2017 4:07 AM
(でも今FileManagerにextensionをはやそうとしてるからSTringでうけてURLで処理してStringで戻すハメに・・・
4:07 AM
なるべくその瞬間に url.path ですね
Avatar
そう、そういうの。
Avatar
omochimetaru 9/22/2017 4:08 AM
API界面だけでStringが出現するようにしてできるだけ型を保ちたい
Avatar
EasyPathを作るか・・・
Avatar
swift-package-manager - The Package Manager for the Swift Programming Language
Avatar
struct Path { private var string: String ... } let path: Path = "/foo" let foo = path["bar"] // /foo/bar
Avatar
omochimetaru 9/22/2017 4:09 AM
@rintaro お。しぶい。AbsとRelを型付けしてる!
Avatar
実装もインターフェイスも詳しくみてないけど、だいたい機能は揃っているんじゃないかな
Avatar
omochimetaru 9/22/2017 4:10 AM
SPMのソースは他のBasic/*.swiftにも依存してそうでなあ
Avatar
Windows 対応とかされてなさそう?
Avatar
omochimetaru 9/22/2017 4:10 AM
Abs / Rel は型付けるか実行時エラーに逃がすか悩むんだけど実例はじめてみた
Avatar
\ にも対応したい
Avatar
Path.swift は単なる文字列操作ですね。
Avatar
omochimetaru 9/22/2017 4:11 AM
var driveLetter
Avatar
FileSystem.swift にファイルシステムが絡む実装がある。
Avatar
なるほど
Avatar
swift-package-manager - The Package Manager for the Swift Programming Language
Avatar
omochimetaru 9/22/2017 4:13 AM
// FIXME: We only support macOS right now.
4:13 AM
FIXMEだ
4:14 AM
/// Helper method to recurse and print the tree. private func recurse(fs: FileSystem, path: AbsolutePath, prefix: String = "") throws { let contents = try fs.getDirectoryContents(path) for (idx, entry) in contents.enumerated() { let isLast = idx == contents.count - 1 let line = prefix + (isLast ? "└── " : "├── ") + entry print(line) let entryPath = path.appending(component: entry) if fs.isDirectory(entryPath) { let childPrefix = prefix + (isLast ? " " : "│ ") try recurse(fs: fs, path: entryPath, prefix: String(childPrefix)) } } }
4:14 AM
楽しそうなのある
Avatar
PathKit - Effortless path operations in Swift
Avatar
omochimetaru 9/22/2017 4:14 AM
あのアスキーアート実装したこと無い 結構簡単に書けるのか・・・
Avatar
omochimetaru 9/22/2017 4:59 AM
public extension Int { func double() -> Int { return self * 2 } } extension Int { public func triple() -> Int { return self * 3 } } print(1.double()) print(1.triple()) public どっちに付けてる?
Avatar
内側派。
Avatar
omochimetaru 9/22/2017 5:13 AM
外側につけた場合、内側が無指定の場合のvisibilityを意味していて、 外側と内側の両方につけた場合は、外側 >= 内側 でないとコンパイラ警告が発生して、 内側だけに付けた場合は、内側の指定が常に有効・・・ 両方とも付けない場合は暗黙のinternal になって、 外側がついていない場合の暗黙のinternal は 外側 >= 内側 ルールは生じない (edited)
Avatar
外側につけてコンパイルエラーになったことがある気がするんだけどあれは何だったんだろう?
Avatar
omochimetaru 9/22/2017 5:14 AM
エラーですか?
5:14 AM
外 < 内 だと警告は出るみたいです
5:15 AM
protocol conformanceを記述する場合はまた話が変わるのかなコレ
Avatar
conformanceは外側必須だった気がする
Avatar
omochimetaru 9/22/2017 5:17 AM
public protocol P0 { func pp() } public extension Int : P0 { public func pp() {} } 1.pp() error: TempGround.playground:5:1: error: 'public' modifier cannot be used with extensions that declare protocol conformances public extension Int : P0 { ^~~~~~~
5:17 AM
むしろ外側に付けられない・・・?あれ?
5:18 AM
@koher の言っているエラーになった話はこれかなあ
Avatar
かも?
Avatar
暗黙的にprotocolのvisibilityが適応されますよということか
Avatar
omochimetaru 9/22/2017 5:24 AM
ああそういうことなのか。
Avatar
確かに extension Foo: PublicProtocol, InternalProtocol {
5:24 AM
これは困る
Avatar
omochimetaru 9/22/2017 5:24 AM
publicなprotocolを、ローカルにconformすることは
5:24 AM
できないのか。
Avatar
そうそう、それはできない。
Avatar
omochimetaru 9/22/2017 5:25 AM
なるほど、まあ確かにできても意味ない。
5:28 AM
public protocol PP0 { func pp0f0() } internal protocol IP0 { func ip0f0() } extension Int : PP0, IP0 { public func pp0f0() {} func ip0f0() {} }
5:28 AM
これはできるんだなあ
Avatar
internalだからな
Avatar
omochimetaru 9/22/2017 5:30 AM
でもそうか conformanceするときには結局メソッドにpublicを明示しないといけないから
5:30 AM
そのパターンと統一しようとすると
5:30 AM
extension自体につけることはなくなってきそう
Avatar
norio_nomura 9/23/2017 3:38 AM
Recursive Protocol Constraintsが入ると、Standard Libraryのプロトコル階層がシンプルになる。 https://github.com/apple/swift/pull/11923/files (edited)
This pull request implements the standard library part of SE-0157: Recursive Protocol Constraints, which includes: Make the SubSequence associated type have the same capabilities as its enclosing ...
Avatar
norio_nomura 9/23/2017 4:06 AM
例えばCollectionだと、現在は非表示になってる_Indexableを使わずに済む様になり、associatedtype Elementvar startIndex: Indexの定義がCollectionへ移り、それらがCollection準拠に必要なものだということが判りやすくなる。 https://github.com/apple/swift/pull/11923/files#diff-1e8313acf545a6c1b6fbb71978690ff6R348
This pull request implements the standard library part of SE-0157: Recursive Protocol Constraints, which includes: Make the SubSequence associated type have the same capabilities as its enclosing ...
Avatar
recursive protocol constraintsは4に入ってましたっけ?
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
Playgroundで触った感じ入ってなさそう
Avatar
「ビルドパフォーマンスが落ちた」とかでrevertされたところまでは覚えてた。
Avatar
ビルドパフォーマンス落ちるのは残当感ある
2:59 AM
コンパイラと戯れるときのデバッグプラクティスが知りたいんですがいい方法無いですか
3:02 AM
PrintExpr使ってprint debugできるっぽいけどコンパイル終わらないケースがあってなかなかつらい
Avatar
どのフェーズを触るかにもよるかもしれないけど、swift -frontend に便利コマンドがたくさんあるイメージ
Avatar
今年はTaPLを割と読み進められていて、型推論をSwiftで実装したり、存在型についてSwiftで考えてみたり している。 そろそろ実際の言語の型システムも読めそうな気持ちになってきたので、なんか読んでみようと思い、一番よく使うSwiftか一番好きなScalaか一番興味があって型システムもイケてそうなRustあたりで迷って、結局Swiftを読んでいる。 これは読みながら書いたメモ。
3:08 AM
これでいけるやろうか
3:08 AM
やったこととしてはwarningの追加で、起きていることはParseErrorを押し退けてwarningが出てしまっていてやばい
Avatar
ちゃんとParserErrorになってるな、うーん、ギョーム終わったら続きやるか
Avatar
ここまでのあらすじ from: #zatsu UIViewController.viewをoverrideしてdidSetしたらStackOverflowすることに気がついた @hiragram#0393 lazy varにdidSet使えないことと関係あるのではと推論するがlazy varはoverrideするとdidSet使えることに気がついてもう大変 (edited)
11:01 AM
@hiragram @Yuta Saito @_ha1f
11:02 AM
@Kishikawa Katsumi
Avatar
議論の対象はlazy varをoverrideするとdidSet使えちゃうのおかしいのでは、という話かな?
Avatar
ちなみにoverride lazy var didSetは初回のlazy setでは呼ばれなかった
11:04 AM
まあ両方ここでしていいんじゃね
Avatar
StackOverflowするやつはやっぱobjcのブリッジ絡みなのかしら。 (edited)
Avatar
objc-runtimeで絶対いらんことしてるという確信に近い直感がある
11:06 AM
lazy var overrideのこれ、使えるなら
11:06 AM
いつぞやのlazy var fatalErrorでIUO使うのをやりたくないワークアラウンドがかなり使いやすくなる
11:06 AM
クラス階層一個増えるのだるいけど
Avatar
たるのん先生的にはlazy varでdidSetが封じられてるのはどうしてなのかしら
Avatar
前までは何か理由があるのかなと思ってたけど、override触った感じ正しく動いてると感じるし
11:07 AM
ただのサボりではという気持ちになってきた
Avatar
11:08 AM
lazyvarfatal定期
Avatar
class A { lazy var hoge: Int = 1 } class B: A { override var hoge: Int = 1 { didSet { print("didSet") } } } こうすると error: variable with getter/setter cannot have an initial value って言われるから lazy varを overrideするとswift側でもcomputed property扱いになるんじゃないかと思った (edited)
Avatar
あー
11:17 AM
class Foo { lazy var _bar : Int = 0 var bar: Int { set { _bar = newValue } get { return _bar } } } 確かにこうすればwillSet, didSet相当の処理は書けますね
11:22 AM
propertyのoverride気持ちを考えるとlazy didSetは使えないがoverrideは使えるはそれはそれで正なのではという気がしてきた
Avatar
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Inheritance.html#//apple_ref/doc/uid/TP40014097-CH17-ID196 Overriding Property Observers You can use property overriding to add property observers to an inherited property. This enables you to be notified when the value of an inherited property changes, regardless of how that property was originally implemented. For more information on property observers, see Property Observers.
regardless of how that property was originally implemented
11:42 AM
正規の動きだ
Avatar
UIViewControllerの方はこれかな https://bugs.swift.org/browse/SR-1000
Avatar
なるほど
11:56 AM
親クラスのプロパティにwillSet/didSetを差し込みたいからオーバーライドする、というのはオーバーライドの正しい使い方ってことね
Avatar
それはそう
Avatar
なるほど
Avatar
UIViewControllerに関しては随分と前からぶっ壊れてたみたいだね
Avatar
だから親のやつがstoredだろうが、はたまたlazyだろうが、関係なくoverrideしたものにはオブザーバーがつけれると
Avatar
1000番だし
Avatar
UIViewControllerはもうね。
11:57 AM
ね。
Avatar
Xcode7から
11:58 AM
まあこっちはUIKitクオリティってことで
Avatar
最小のコード量で押すとぶっ壊れるツボを見つけるみたいなの一周回って最近楽しくなってきたわ
Avatar
StackOverflowするやつはやっぱobjcのブリッジ絡みなのかしら。 1. didSet 呼び出し前にoldValue (view)が必要 2. -[UIViewController view] 3. -[UIViewController loadViewIfRequired] 4. -[UIViewController setValue:forKey:] 5. 1へ ってなってますね。 (edited)
Avatar
didSetのスコープでプロパティ触った場合ってdidSetに来なかったですよね
12:54 AM
あ、これはdidSetの前でswift関係なく無限ループしてるのか
Avatar
If anybody's looking for a relatively straightforward Swift starter design/implementation task, here you go: https://t.co/E1Li3BtxnA
1:00 AM
まさにこの問題ぽいのですが、シンクロすごい。
👀 1
Avatar
これっすね
Avatar
実際オブザーバー付いてると、現状 mutate な操作でも無条件でコピーされてしまうから早く実装されて欲しいです。 (edited)
Avatar
なるほど swift didSetがoldValueを要求↔objcがcurrentValueにアクセス ここを無限に繰り返してる
Avatar
omochimetaru 9/26/2017 3:58 AM
なるほど
Avatar
ナルホディウス
9:31 AM
へんなのふんだ
Avatar
PC1.aaa デフォルト実装 は class 制約がついていないから PC0.aaa を満たせないっていうことなのか。
Avatar
omochimetaru 9/26/2017 9:36 AM
varfunc と違って、 mutating を指定することはできないけど
9:36 AM
内部的には mutating 付きの struct 向けの var set と、 class 向けの nonmutatingvar set
9:36 AM
区別されている気がします。
9:37 AM
で、 PC0: class ついてるから nonmutating set が要求されるようになっていて、 PC1 は ついてないから mutating set を実装していて、噛み合わない。
Avatar
public protocol A { var aaa: Int { get set } } extension A { public var aaa: Int { get { return 1 } set { () } } } public protocol B: class { var bbb: Int { get set } } extension B { public var bbb: Int { get { return 1 } set { () } } } で sil 出すと
9:45 AM
// A.aaa.setter sil @_T04test1APAAE3aaaSifs : $@convention(method) <Self where Self : A> (Int, @inout Self) -> () { // %0 // user: %2 // %1 // user: %3 bb0(%0 : $Int, %1 : $*Self): debug_value %0 : $Int, let, name "newValue", argno 1 // id: %2 debug_value_addr %1 : $*Self, var, name "self", argno 2 // id: %3 %4 = tuple () // user: %5 return %4 : $() // id: %5 } // end sil function '_T04test1APAAE3aaaSifs' // B.bbb.setter sil @_T04test1BPAAE3bbbSifs : $@convention(method) <Self where Self : B> (Int, @guaranteed Self) -> () { // %0 // user: %2 // %1 // user: %3 bb0(%0 : $Int, %1 : $Self): debug_value %0 : $Int, let, name "newValue", argno 1 // id: %2 debug_value %1 : $Self, let, name "self", argno 2 // id: %3 %4 = tuple () // user: %5 return %4 : $() // id: %5 } // end sil function '_T04test1BPAAE3bbbSifs'
9:45 AM
ABIが違う。
Avatar
omochimetaru 9/26/2017 9:45 AM
@inout Self はまさに mutating func の self渡しですね
Avatar
@inout vs @guaranteed
Avatar
omochimetaru 9/26/2017 9:46 AM
@guaranteed はよくわかっていない。 Ownership Manifesto だと nonmutating funcself は shared渡しになるって書いてあるけど、SILでは名前が違うんかな。
Avatar
僕も @guaranteed の意味よく知らないです。 けど class つけると リファレンス値の値渡しになるのかと思います。
9:52 AM
public protocol B : class { var bbb: Int { get set } static var initial: Self { get } } extension B { public var bbb: Int { get { return 1 } set { self = Self.initial } } } test.swift:9:16: error: cannot assign to value: 'self' is immutable set { self = Self.initial } ~~~~ ^ class 付いてないと通る。
Avatar
omochimetaru 9/26/2017 9:53 AM
ああ、書いてなかったw そうなんですよ!w
Avatar
classついてないこのprotocolをclassに実装したらどうなるんですか
Avatar
omochimetaru 9/26/2017 9:55 AM
それ自体はできる
Avatar
self置換できる
Avatar
public protocol B { var bbb: Int { get set } static var initial: Self { get } } extension B { public var bbb: Int { get { return 1 } set { self = Self.initial } } } final class C : B { static var initial: C { return C() } } var c = C() print(ObjectIdentifier(c)) c.bbb = 1 print(ObjectIdentifier(c)) ObjectIdentifier(0x00007fe1f5e04930) ObjectIdentifier(0x00007fe1f5d113b0) (edited)
Avatar
finalじゃないと怒らるのはinitialの型か
Avatar
omochimetaru 9/26/2017 9:57 AM
出たw
9:57 AM
let c だと b.ccc = 1 が呼び出せないやつ
Avatar
let ns = (0..<10).map { $0 } let ps = ns[2, 3, 5, 7] 仮に↑こんなことができるとして、 ps[2] // 2 ps[3] // 3 ps[4] // エラー ps[5] // 5 のようになる Collection って標準ライブラリにないですよね? ArraySlice のすごいやつみたいな。
Avatar
omochimetaru 9/27/2017 6:47 AM
Dictionaryにして []! で取り出すと同じ?
Avatar
整数の index に対して index が飛び飛びになるような Collection (edited)
6:49 AM
ArraySlicestartIndex0 とは限らないし、 endIndexcount とは限らないけど、間は詰まってることが保証されている。
6:49 AM
Dictionaryにして []! で取り出すと同じ?
同じといえば同じかもしれないけど、 index で表されてるからちょっと違う。
Avatar
ArraySliceとくらべて保持するデータが多いしあんまり有用そうでは無さそうな……
Avatar
omochimetaru 9/27/2017 6:51 AM
@t.ae Optionalにして埋めて持てばデータ量はArraySliceとほぼおなじかも
6:51 AM
↑の例だと元々のArrayがあるみたいだから
6:52 AM
全部埋めたメモリサイズはそもそも許容される
Avatar
Optionalにして埋めて持てば
よくわからないですけどインデックス一覧は保持する必要ありますよね?
Avatar
omochimetaru 9/27/2017 6:52 AM
いや
6:52 AM
内部的に Array<Int?>
6:52 AM
nilならクラッシュさせる
Avatar
元のArrayのサイズXとして ArraySliceだと総合してもX+aですみますけど これだと2Xになっちゃうよなぁと思ったんですが
Avatar
↓みたいなことができたらいいなぁと考えてた。 users[where: { $0.birthday == today }].update { $0.age += 1 }
6:54 AM
前話してた update メソッドがあればコレクションの要素の更新ができるんだけど、
Avatar
omochimetaru 9/27/2017 6:54 AM
2Xにはなるね。
Avatar
SQL で WHERE で絞って更新みたいなのができない。
6:54 AM
値型だと。
Avatar
それぼくは何か中間データ型おいて似たようなことやらせるのかきましたよ
Avatar
omochimetaru 9/27/2017 6:55 AM
WHERE が遅延しないといけないっすね
6:55 AM
C# の LinQ みたい。
Avatar
もちろん users.update(where: { $0.birthday == today }) { $0.age += 1} ならできるけど不細工なので。
Avatar
omochimetaru 9/27/2017 6:56 AM
LinQでもできない気がするな・・・
Avatar
で、飛び飛びインデックス Collection があれば、 subscript(where:) にすることでできないかと思って。
Avatar
omochimetaru 9/27/2017 6:56 AM
あーそれって結局
6:56 AM
.update を受ける型が
6:56 AM
いまいった特殊なやつにすり替わるってことですよね?
Avatar
そこがミュータブルじゃないから update が無理かな? (edited)
Avatar
コレクションのsubscriptをつくって頑張ればできるはず https://github.com/t-ae/Swim readmeに書いてる例がそれっぽいかも image[col: 2] += 1
Swim - Image library for Swift
Avatar
omochimetaru 9/27/2017 6:57 AM
.where
6:57 AM
絞り込み条件と元のArrayを保持した型にさしかえて
6:58 AM
update のところで where のフィルタを処理するとできそう
Avatar
@t.ae それは↑に書いた 2 引数 update と同じだから、 where で一度絞り込んだ上で update を実行したい。
6:58 AM
本当は filter でできれば一番いいんだけど・・・。
6:58 AM
参照型だと簡単なんだけど、値型だと難しい。
Avatar
image[col: 2].red += 1 みたいなのもできます
6:59 AM
あーでもちょっと違うかな
Avatar
omochimetaru 9/27/2017 6:59 AM
あー inout型をプロパティに保持できないと
6:59 AM
メソッド一回しか
6:59 AM
先送りできないのか。
Avatar
そんな感じ
Avatar
omochimetaru 9/27/2017 6:59 AM
さっき言ってたインデックスなやつがあったとしても
7:00 AM
もともとのArrayに代入する文が必要になっちゃう。
Avatar
ん?そこの一段目は subscriptset で戻すんだけど
Avatar
omochimetaru 9/27/2017 7:00 AM
あ〜なるほど
Avatar
二段目の mutating func である update
7:00 AM
呼べない気がしてきた。
Avatar
omochimetaru 9/27/2017 7:00 AM
subscript だから = になるのか
Avatar
上に張った僕のはsubscript setを定義して +=とかを実装してますね
Avatar
omochimetaru 9/27/2017 7:02 AM
subscriptで変な型にして、変な型に対してmutating funcかけて
7:02 AM
変な型として元のarrayに戻す
7:02 AM
って手順だとできるのか。。
Avatar
そうですね。
7:03 AM
users[where~] = users[where~].update {}という形になるので mutating funcである必要はないかも?
Avatar
omochimetaru 9/27/2017 7:03 AM
ちょっとやってみるか
Avatar
その再代入はしたくない
7:09 AM
それを subscript にすることで避けられないかと。
7:09 AM
extension Array { mutating func update(_ modify: (inout Element) throws -> ()) rethrows { for i in 0..<count { try modify(&self[i]) } } } extension ArraySlice { mutating func update(_ modify: (inout Element) throws -> ()) rethrows { for i in startIndex..<endIndex { try modify(&self[i]) } } }
Avatar
mutating funcである必要はないかも?
は大嘘でした
Avatar
var ns = (0..<100).map { $0 }
7:10 AM
↓これはできるし ns.update { $0 += 100 }
7:11 AM
↓これもできるけど var ms = ns[50..<60] ms.update { $0 += 100 }
7:11 AM
↓これはできなかった。 ns[20..<30].update { $0 += 100 }
Avatar
omochimetaru 9/27/2017 7:12 AM
そもそもsubscriptにクロージャとれますか?
7:12 AM
いまそこでつまづいた
Avatar
え?とれない理由があるの??
Avatar
omochimetaru 9/27/2017 7:13 AM
TempGround.playground:28:2: note: overloads for 'subscript' exist with these partially matching parameter lists: (Int), (Range<Int>), ((Element) -> Bool), (Range<Self.Index>), (R), ((UnboundedRange_) -> ()) s[wh: { (x: Int) -> Bool in x % 2 == 0 }] ^
7:14 AM
なんか書き方をミスってるのかな
7:15 AM
あ、できた、ラベルつけちゃいけない???
Avatar
subscript は subscript(wh where: (Element) -> Bool) みたいにラベル明示しないと。
🙏 1
Avatar
omochimetaru 9/27/2017 7:16 AM
あ、2個かくのか。
Avatar
それ地味に分かりにくいですよね
Avatar
omochimetaru 9/27/2017 7:17 AM
var s = [0, 1, 2, 3, 4] print(s) s[`where`: { $0 % 2 == 0 }].update { (x: inout Int) -> Void in x += 100 } print(s)
Avatar
Dictionary.Value コレクションの var dict:[String: [Int]] = ["foo": [], "bar": [1,2,3]] dict.values[dict.index(forKey: "foo")!].append(42) なんかは、stdlibならではのかなり特殊なことやっているので、やりたいこと実現するのはなかなか厳しいかも。
Avatar
omochimetaru 9/27/2017 7:17 AM
[0, 1, 2, 3, 4] [100, 1, 102, 3, 104]
7:17 AM
できた (edited)
7:18 AM
実用性は無いしsubscriptのsetにバグがあるけど
7:18 AM
とりあえず見かけ上実現してみたw
Avatar
なるほどー
Avatar
omochimetaru 9/27/2017 7:20 AM
subscript特有の振る舞いを利用したトリックとしては面白いですね
7:21 AM
Playground execution failed: error: TempGround.playground:28:38: error: passing value of type 'Int' to an inout parameter requires explicit '&' s[`where`: { $0 % 2 == 0 }].update { $0 += 100 } ^ &
7:21 AM
↑これっていま推論できないんです?
7:21 AM
エラーメッセージも意味不明
Avatar
おお、まさに var dict:[String: [Int]] = ["foo": [], "bar": [1,2,3]] dict.values[dict.index(forKey: "foo")!].append(42) みたいなことですねやりたいの。
Avatar
omochimetaru 9/27/2017 7:24 AM
.values[] ここ何が
Avatar
dictionary.valuesがdictionaryをmutatingできるのイミフすぎる
Avatar
omochimetaru 9/27/2017 7:25 AM
これ、内部でもってる参照型のstorage本体を操作してる?
Avatar
ですです。
🙌 1
Avatar
あー
Avatar
omochimetaru 9/27/2017 7:25 AM
ずる
Avatar
set,getなcomputed propertyなら一応動きを再現するものは作れるか
Avatar
パフォーマンスはさておき
Avatar
omochimetaru 9/27/2017 7:27 AM
/// A view of a dictionary's values. public struct Values : MutableCollection { public typealias Element = Value internal var _variantBuffer: Dictionary._VariantBuffer internal init(_ _dictionary: Dictionary) { self._variantBuffer = _dictionary._variantBuffer }
7:27 AM
getのほうも内部参照コピーだな
7:28 AM
同じようなアプローチでやるとどうなるんだろ なんとかなるきもする?
Avatar
@tarunon そうなんです。それが値型をコレクションを where, update とつないで更新できないかと思った出発点です。
Avatar
subscriptなら引数取ってmutatingにできる、なるほど確かに
Avatar
作れたら面白いと考えてるのは(実際に作るかはさておき)値型データベースライブラリで、 where して update するにはこういう技が必要だろうなと。その場合は自作型になるから↑の Dictionary がやってるような技も使えそう。 (edited)
7:35 AM
そうすると、クエリーの結果が値型コレクションで返ってくるんだけど、トランザクションによって分離されることを値型が状態を共有しないことで表現できればおもしろそう。
7:41 AM
Dictionaryでindexもつ版
Avatar
本当は users.filter { $0.birthday == today }.update { $0.age += 1 } が出来たらいいんだけど値型には無理。
Avatar
UnsafeMutablePointer で無理矢理。。
Avatar
omochimetaru 9/27/2017 7:45 AM
values のトリックは computed var なら戻してこれるのか・・・?
Avatar
いけるはず
Avatar
omochimetaru 9/27/2017 7:45 AM
やってみる
7:51 AM
できた
7:51 AM
旧 s[where: { $0 % 2 == 0 }].update { (x: inout Int) in x += 100 } 新 s.where[{ $0 % 2 == 0 }].update { (x: inout Int) in x += 100 } (edited)
7:51 AM
var filterは出来ないんだっけ
Avatar
omochimetaru 9/27/2017 7:52 AM
結局 [{ }] が出てきてださいなあ
Avatar
まあそこはsubscriptの制約がね
7:52 AM
functionのreturn valueにinout Tが使えたらなぁ
7:52 AM
でも崩壊するか
Avatar
omochimetaru 9/27/2017 7:52 AM
うん
7:52 AM
それはやめとこうや、って書いてある
Avatar
s.where[] { $0 % 2 == 0 } ...
👀 2
Avatar
omochimetaru 9/27/2017 7:53 AM
www
7:53 AM
いけたwww
7:54 AM
subscript後置できたんだ・・・
Avatar
Avatar
知らなかった・・・
7:55 AM
さすがに [] は省略できない?
7:55 AM
() みたいに
Avatar
omochimetaru 9/27/2017 7:55 AM
whereにくっついちゃってダメっぽい
Avatar
そりゃむりか
Avatar
omochimetaru 9/28/2017 1:39 AM
This change in theory should allow us to remove a special stdlib-only sil-serialize-all compilation mode. rdar://problem/34138683
1:40 AM
気になるスレ ひたすら @_inlineable が追加されるdiff
Avatar
正確なところはわかないけど、 sil-serialize-all しなくても @_inlineable で .swiftmodule に実装SILが埋め込まれるようになるから、 --sil-serialize-all 要らなくなるって話なのかなと。
Avatar
omochimetaru 9/28/2017 1:43 AM
あーなるほど、それで1コメが「This change in theory should allow us to remove a special stdlib-only sil-serialize-all compilation mode.」なんですね
1:44 AM
rdar://problem/34138683 ←これの内容の見方をおしえてください @rintaro
Avatar
rdar は Apple 内部のバグトラッキングシステムなので、外からは見えません。 https://openradar.appspot.com にバグ登録者が登録していれば見えるけど、これはたぶん内部登録なので、わからないですねー
Avatar
omochimetaru 9/28/2017 1:46 AM
なるほど。
Avatar
omochimetaru 9/28/2017 9:09 AM
最近Swiftリポジトリをwatchしてみたんだけど、プルリクに動きがあると思ったら、botに「テストしてくれや」って話しかけてるだけの事が多くてアレ
Avatar
gmailでフィルターしてゴミ箱にぶち込んでる
Avatar
omochimetaru 9/28/2017 9:31 AM
githubのウェブの右上の通知アイコン使ってるんだよね
Avatar
それはきびしい
Avatar
omochimetaru 9/28/2017 9:32 AM
ははは
Avatar
githubからの通知メールをGmailで開くと https://github.com/notifications でも既読になるから、Gmailでざっと見て必要ならgithubのwebへ、って感じにしてる。
GitHub is where people build software. More than 24 million people use GitHub to discover, fork, and contribute to over 67 million projects.
Avatar
omochimetaru 9/29/2017 1:14 AM
えっ、そうなんですか そんな謎技術あるのか
Avatar
omochimetaru 9/29/2017 1:41 AM
本当だ・・・
1:47 AM
[swift-evolution] Idea: Public Access Modifier Respected in Type Definition
1:48 AM
public struct Coordinate { /// Should default to public. let latitude: Double /// Should default to public. let longitude: Double /// Should default to public init?(latitude: Double, longitude: Double) { guard validate(latitude: latitude, longitude: longitude) else { return nil } … } } internal extension Coordinate { /// Convenience initialiser to me used internally within the module. init(coordinate: CLLocationCoordinate2D) { … } }
1:49 AM
struct/class と extension で visibility がメンバにも適用されたりされなかったりするのわかりにくいからstructの挙動を↑に変えないか?ってメール
1:49 AM
この前もextensionで混乱したし一理あると思ったw
Avatar
いいかも。
Avatar
omochimetaru 9/29/2017 2:13 AM
賛成メールを送ってみた
Avatar
async, awaitについてのswift-evolutionでの議論、量が多くて早々に追っかけるのをやめてしまったのですが、今どうなってるか知ってる人いますか?
Avatar
最初追ってましたが、メールが多すぎたのと、先月後半から忙しくなって追えてません。
Avatar
話題としてReactiveStreamingがちらほら出てきてるのは見てたんですが中身は追いかけれてない
Avatar
僕は func beginAsync(_ body: () async throws -> Void) rethrows -> Voidthrowsrethrows はいらないだろうと思ってます。それは書いたけど、把握してた範囲では返事なしでした。
Avatar
ここをチェックしておけば良さげ? https://gist.github.com/lattner
GitHub is where people build software. More than 24 million people use GitHub to discover, fork, and contribute to over 68 million projects.
👀 1
Avatar
その二つですね。
Avatar
async await欲しい
Avatar
Swiftのasync/await、他の言語と比べても最高だと思うんですよね。
2:27 AM
特にthrows/tryとの組み合わせが素晴らしい。
Avatar
結局、非同期処理の前にerrorが出ても型としてはasync throws () -> Tですよね
Avatar
@tarunon ですね。
Avatar
beginAsyncのthrow rethrowが要らないのがぱっと理解できない
2:30 AM
あ、勘違いだ、これはcallbackをasyncにする奴ではなく
Avatar
omochimetaru 10/2/2017 2:31 AM
非同期発火前のthorwsについてはどうせrethrowsできないから
2:31 AM
そこのハンドル漏れが出るよりは
Avatar
処理を投げっぱなしにする奴か。rethrowsだとErrorの時に待つみたいな意味不明なことになる
Avatar
omochimetaru 10/2/2017 2:31 AM
非同期発火前も含めて禁止したほうがマシではって意見
Avatar
待つんじゃなくて
Avatar
omochimetaru 10/2/2017 2:31 AM
待つんじゃなくて無視だったかクラッシュだったか、とにかく、別扱い
Avatar
非同期突入前の
Avatar
callbackをasync化する話と混ざってました
Avatar
Errorrethrow ですね。
Avatar
omochimetaru 10/2/2017 2:32 AM
しかも非同期突入前のthrowsについてはどうせbeginAsyncの手前に持ってこれるから困らないはずなんだよなあ
Avatar
この機能って提供する必要あるのかな (edited)
Avatar
単に Core Team が見落としてるだけな可能性もあるんだけど、スレッドが長すぎて
2:33 AM
書いたとしても読まれるかわからない
2:33 AM
ってか一度書いた
Avatar
omochimetaru 10/2/2017 2:33 AM
throwsのところは置いといて提供自体は必要だと思う
Avatar
do { _ = await foo() } つまりこれと同じでしょ?
Avatar
いや
2:34 AM
えっと
Avatar
omochimetaru 10/2/2017 2:34 AM
それは提案されてなくない?
Avatar
まず do { await } はまだないのと
✌ 1
2:35 AM
仮に導入するならそれはブロックじゃないと整合性がとれないです。
Avatar
無いのか…
Avatar
beginAsync はノンブロッキングなやつだから
Avatar
んー
2:36 AM
末尾にblock書く/ないで、blockingとnon-blocking区別できそうだけども
Avatar
それだと意図しないただの do ブロック(普通の言語の無名スコープ相当)の中に await 書いたら変な挙動になっちゃいます。
2:37 AM
末尾に nonblock とか書くことはできますが、
2:37 AM
あまりキレイじゃないと思うんですよねぇ。
2:37 AM
標準ライブラリに関数として beginAsync 追加すれば対応できることですし。
Avatar
doの無名スコープとしての用法があるのか。いつだったか、async { await }にしようみたいなのもありましたね
Avatar
一方で、 do { await } blockdo { try } catch と対応するのでキレイなんですよね。
Avatar
ところで
2:40 AM
_ = await foo() これだけでもノンブロッキング感あるんですが
Avatar
やっと見つかった。早く移行してほしい・・・。 https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170814/039024.html
Avatar
そこはどうなってんだろ
Avatar
それだとその関数が
2:41 AM
async必須になっちゃいます。
Avatar
なっちゃうのか
Avatar
で、どこまでもasyncが連鎖してしまうので
Avatar
そうか…
Avatar
根本で囲う必要があって
2:41 AM
それが beginAsync ですね。
2:42 AM
コールバックを async 化するのが suspendAsync
Avatar
beginAsyncって、逆にコールバック化する関数で、クロージャのデフォルトにnilだと良いと思ったんですがそう言う提案はないですかね?
2:46 AM
そうすると、throwsとそうじゃないのでbeginAsyncをオーバーロードして、結果も全部綺麗になりそうだけど
Avatar
どういうシグネチャにするイメージですか?
Avatar
func beginAsync<T>(_ f: () async -> T, callback = ((T) -> ())? = nil) func beginAsync<T>(_ f: () async throws -> T, callback = ((T?, Error?) -> ())? = nil) こうかな (edited)
Avatar
async, throws の位置が変な気が・・・
Avatar
iPhoneなので赦されたし
👍 1
2:50 AM
なおした
2:51 AM
まあこれでやりたいこと全部出来るはず
2:51 AM
suspendの逆でもあるし、解りやすくて良い
Avatar
うーん、まず beginAsyncthrows な関数を渡したいっていうのがよくわからないんですよね。
Avatar
それはthrows渡せないと、beginAsync使えなくなるのでは
Avatar
beginAsync { let foo = try foo() await bar(foo) }
2:52 AM
みたいなケースは
2:52 AM
let foo = try foo() beginAsync { await bar(foo) }
2:52 AM
に書き換え可能だと思うんですよ。
Avatar
awaitの中でthrowは無理くないですか?
Avatar
それは非同期的に発生するから
2:53 AM
beginAsync では無理です。
Avatar
というか、async throws組み合わせて使える言語設計なのに、そこだけ自力で頑張れっていうと、ちょっと違う気がする
2:53 AM
さっきのoverloadingなbeginAsyncではいけるのでは?
Avatar
beginAsync { do { await try foo() } catch { ... } }
2:54 AM
beginAsyncthrows/rethrows を封じれば↑が強制されるんですよね。
2:54 AM
これで十分かと。
Avatar
omochimetaru 10/2/2017 2:54 AM
tarunonのアイデアはわかったけど func startRequest(_ request: Request, success: (Response) -> Void, failure: (Error) -> Void) { beginAsync { do { success(await try startRequestAsync(request)) } catch let e { failure(e) } } }
2:54 AM
↑あまりに簡単に自分で書けるからそこはいらないのでは
Avatar
簡単に書けるから要らない、ならそもbeginAsync自体が
Avatar
omochimetaru 10/2/2017 2:55 AM
あと、asyncフェーズの中では、途中の結果とか、途中のエラーとかもあるから
2:55 AM
「ok1個 | 失敗1個」のシグネチャに制限するのも
2:55 AM
ある特定のシナリオにフォーカスしすぎてると思う
2:56 AM
言語側で用意するのは「結果を捕まえずにasyncを発火する」っていう最小限の機能だけで良いと思う
Avatar
それはErrorの型とパターンマッチでなんとかするって話じゃないの
Avatar
コールバックが嫌だから async 化したいわけで、コールバック化できてもうれしいことはないような?
Avatar
omochimetaru 10/2/2017 2:57 AM
簡単に書けるから要らない、ならそもbeginAsync自体が
beginAsync自体は他の機能で代替できないと思う
Avatar
そして、 beginAsync の中で try したいときは発火前については外だしできるはずで
Avatar
omochimetaru 10/2/2017 2:57 AM
「non async な func の中から async な処理を開始する」にはなんらかの言語サポートが必要
Avatar
ああ、beginAsync自体は必須なのか、そうか
Avatar
beginAsyncthrows なクロージャを渡せる必要性がよくわからない・・・
Avatar
omochimetaru 10/2/2017 2:58 AM
で、現状の提案のbeginAsyncから throws と rethrows を取り除くアイデアは僕も賛成で、 なぜならそれは必須な部分じゃないという理由がここにもマッチする
2:58 AM
必須じゃないのはそのエラーを投げる処理だけbeginAsyncの前にかけるから。
Avatar
async throws組み合わせて使える言語設計なのに、そこだけ自力で頑張れっていうと、ちょっと違う気がする 僕はこれを考えていて
Avatar
さらに、非同期関数の多くは async throws になるだろうから、 beginAsync { try await foo() } にコンパイラのチェックが働かなくて、エラーハンドリングがタイプセーフでなくなってしまう。
Avatar
omochimetaru 10/2/2017 3:01 AM
@koher 最初のawaitまでのタイミングでthrowsになっていることと、それ以降でthrowsになることをシグネチャとして区別できれば良かった Result<Promise<T>> と Result<Promise<Result<T>> と Promise<Result<T>> の区別。
Avatar
いやーそれきつくない?
Avatar
omochimetaru 10/2/2017 3:01 AM
でもそれはややこしいから Result<Promise<T>> と Result<Promise<Result<T>> は無いってことになってしまって
3:01 AM
Promise<T> と Promise<Result<T>> だけでいこうって
3:01 AM
方針
3:02 AM
うん、僕も問題が起きるのはbeginAsyncだけだと思うから、これでいいと思う
Avatar
func beginAsync(_ body: () throws async throws -> Void) rethrows[0] -> Void
3:02 AM
みたいなことしないといけない・・・
Avatar
omochimetaru 10/2/2017 3:02 AM
beginAsyncが現状の提案のまま破綻しない世界線に行くとしたら何があったかという仮定の話
Avatar
throws が複数あるときに選択的に rethrow する話はどこか(多分 Error Handling Rationale )に書いてあった。
3:03 AM
今は実装しないけど、って。
Avatar
nonblocking化とErrorハンドリングをスッとやるなら、コールバック化が一番良いと思うんだけどな
Avatar
↓だめですか? beginAsync { do { await try foo() } catch { ... } }
3:04 AM
可読性も高いし do/try/catch 使えるし。
Avatar
あー、中でやれと言う話になるのか
3:04 AM
それはそっちのほうが良さそうですね
Avatar
omochimetaru 10/2/2017 3:04 AM
あと並列タスク発行とかの目的であれば 提案されてる Future があれば十分じゃない?
Avatar
beginAsync から throws/rethrows を取り除けば、↑のエラー処理が(必要な場合は)強制されていい感じになるんですよねぇ。
Avatar
omochimetaru 10/2/2017 3: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 } ↑これの、dataREsourceとimageResourceは並列発火されて、 それぞれ .get() のところで(awaitで)待つ。 (edited)
3:06 AM
Futureのコンストラクタ呼び出しで見れば non-blocking化されてる。
12:51 AM
stdlib なみの最適化がサードパーティモジュールでも可能になる
❣ 4
Avatar
おおおおお
12:58 AM
プロポザルの形だ 読むぞ!!
Avatar
これは良さそう
1:02 AM
でもライブラリのコードが@inlinableだらけになりそう
Avatar
omochimetaru 10/3/2017 1:25 AM
読んだ
1:26 AM
どうでもいいけどinlineableじゃなくてinlinableなんだな
Avatar
Strideableがどんどん気になる
Avatar
こっちは辞書にのってますしねぇ
Avatar
omochimetaru 10/3/2017 1:27 AM
inlinableにしない場合のメリットは、ソースが秘匿できる、おそらくコンパイルが早くなる、privateメソッドが呼び出せる
1:27 AM
inlinableなpublicメソッドの内部では、privateなメソッドが呼び出せないし、ローカルな型が定義できないとのこと
1:30 AM
あとライブラリが変更されたときにユーザ側のリビルドをしないと古いコードを取り込んだままになる、とかもあるね
Avatar
inlinableなprivateメソッド(そんなもの作れるのか知らないけど)も呼び出せないの?
Avatar
omochimetaru 10/3/2017 1:30 AM
作れないです
1:30 AM
inlinableはpublicにしか付けられないって書いてある
Avatar
うーん、それ結構イマイチだなぁ。
Avatar
omochimetaru 10/3/2017 1:31 AM
もしできるなら理屈としてはできますね。
Avatar
別に秘匿したいわけじゃないけど
1:31 AM
APIとしては公開しても意味がないので公開したくないってありそう
Avatar
omochimetaru 10/3/2017 1:31 AM
ライブラリとしては提供したくないあまり保守性の高くないメソッド
Avatar
うん
Avatar
omochimetaru 10/3/2017 1:31 AM
ドキュメントプライベート的な小道具
1:31 AM
そうですよね。
Avatar
そうそう
Avatar
internalならいいんですかね? 内部はともかく外向きはあんまり問題にならないならいいんですが
Avatar
omochimetaru 10/3/2017 1:31 AM
わかる
1:31 AM
internalもだめ
Avatar
ええ
Avatar
omochimetaru 10/3/2017 1:31 AM
ようするにコードが
1:32 AM
ユーザ側に展開される。
Avatar
大体インライン化したいものってそういう小道具な気がするんだけどなぁ。
Avatar
omochimetaru 10/3/2017 1:32 AM
inlinable declarations can only reference other public declarations. This is because they can be emitted into the client binary, and are therefore limited to referencing symbols that the client binary can reference.
1:32 AM
can only reference other public.
1:32 AM
そこらへんの話題はブチこんでみたほうがいいかもしれんなあ
1:32 AM
スレに
Avatar
あと、 @inlinable でないとインライン化は絶対されないの?
Avatar
omochimetaru 10/3/2017 1:33 AM
されないですね
1:33 AM
コードが出荷されない
Avatar
あー、えっと
1:33 AM
一つのモジュールの中でも
1:33 AM
それはされるのか。
Avatar
omochimetaru 10/3/2017 1:33 AM
いや、モジュールの内部であれば
1:33 AM
internalやprivate
1:33 AM
全部からめて
1:33 AM
アグレッシブなインライン化は起きるって
1:33 AM
冒頭に書いてある。
1:33 AM
それはいままでもそう。
Avatar
なるほど、モジュールをまたいだインライン化を制御するためのものなのか。
Avatar
omochimetaru 10/3/2017 1:34 AM
そうですね
Avatar
今のところ自前で最適化を書いていくほうが実行効率は良いってことですかね
Avatar
omochimetaru 10/3/2017 1:34 AM
今のところ?とは?
Avatar
うーん、それにしても EasyImagy みたいなのでオープンソースだし秘匿したいものは何もないけど、冗長なコードを排除するために internal な小道具をいっぱい作ってるケースでは微妙そうだ・・・
Avatar
今後これが改善されるとして
Avatar
omochimetaru 10/3/2017 1:35 AM
@koher 現状できる方法だと @avaiable を駆使してpublicだけど使わせないようにするとか。
Avatar
そんなことできるっけ?
Avatar
それ内部でも警告出ません?
Avatar
omochimetaru 10/3/2017 1:35 AM
@hiragram がよくやってる
Avatar
なるほど
Avatar
omochimetaru 10/3/2017 1:36 AM
それ内部でも警告出ません?
出そうw
Avatar
よばれた
Avatar
omochimetaru 10/3/2017 1:36 AM
そこなんとかならんかな。
1:37 AM
@hiragram publicだけど使わせないようにする@availableの技って自分で使うところも警告出ちゃう?
Avatar
わしがしってるのはアクセスレベル関係なく
1:37 AM
警告出したければdeprecatedでエラーにしたければobsoletedにしている
Avatar
omochimetaru 10/3/2017 1:37 AM
Private @inlinable functions are useful. For example, you might want a helper function to be inlined into a public @inlinable function for performance, but you don't want that helper function to be called by outside clients directly.
Avatar
ないぶでもでる
Avatar
omochimetaru 10/3/2017 1:38 AM
スレにその話題投げてる人おるな
1:38 AM
内部でも出ちゃうか、じゃあ、この場合はダメだなあ
1:38 AM
deprecatedじゃなくてobsolatedってのもあるんだ。
Avatar
それぞれ非推奨と廃止だね
Avatar
omochimetaru 10/3/2017 1:39 AM
廃止なら消せよって気もする
Avatar
unavailableもあるけどそれはだいぶ大雑把に使用不能にする感じで、deprecatedとobsoletedはバージョン指定してそれ以降のバージョンで警告やエラーになる
Avatar
omochimetaru 10/3/2017 1:40 AM
あーなるほど
1:40 AM
たとえばiOS SDKのiOS11では存在しない関数をつかっていても、obsoletedしておけばコンパイルできるのかな?
Avatar
特にルールは決めてないけど広く使われてるAPI変えるときはまずdeprecatedつけて、移行先が用意できたらobsoletedにして、ある程度経過したら消す
1:41 AM
あ、バージョンっていうのはアプリやフレームワーク自体のバージョンね
1:41 AM
Swift側からUIKitとかのヘッダみるとたまに@availableついてるきがする
Avatar
omochimetaru 10/3/2017 1:42 AM
あ、なるほど
Avatar
omochimetaru 10/3/2017 1:49 AM
That’s what @_versioned is currently for. You can define a function as @_versioned @_inlineable and reference it from other public inlinable functions, without making it visible to AST-level lookup.
(edited)
1:50 AM
うーん、 @_versioned @_inlineable をつければそれはできるけど @_versioned 周りは将来別のプロポザルとしてやりたい
1:50 AM
みたいな流れになっているけどよく意味がわからん
Avatar
廃止で消しちゃうと、代わりにこのメソッド使えみたいな案内出せなくなるからね
Avatar
omochimetaru 10/3/2017 1:53 AM
obsoleted はそうか
1:53 AM
あ、versionedの話は、private なメソッドを 呼び出す話です
Avatar
これとは別に、availabilityにアクセス修飾子つけたいみたいな話を @rintaro がしてなかったっけ?
1:55 AM
現状は中だけで使えて外側には使わせないみたいなのは無理だと思う
Avatar
omochimetaru 10/3/2017 1:56 AM
[swift-evolution] [Generics] [Pitch] Dependent Types
このスレも気になるな
Avatar
Re-pitch: remove(where:)
これも気になってる
1:57 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 10/3/2017 1:57 AM
え、それって気になるやつなんですか
1:58 AM
何をそんなに話してるんだろうと思ってた
1:58 AM
extensionでよくつくってるけどstdlib側につけてくれってだけの話ではない?
Avatar
filterのinout版ですよねこれ
1:58 AM
inout reduceがあるのでその中で使う需要がある
Avatar
inout もそうだし
1:59 AM
filter と判定基準が逆だから
Avatar
あ、逆だ、確かに
Avatar
どう折り合いをつけていくのかを話してる感じ (edited)
Avatar
omochimetaru 10/3/2017 2:00 AM
ふむふむ
Avatar
このまえの update の話にも通ずる (edited)
2:01 AM
というか、このスレを見かけて思い出してこの前書いた。
2:02 AM
Swift が値型中心である以上 inout は重要なキーになると思ってて、これまで標準ライブラリに reduce(into:_:) がなかったことからもその可能性が見過ごされてたんじゃないかなぁ。
2:02 AM
inout な高階関数なんか考えたことなかったし。
2:03 AM
(見過ごされてたというか、できなかったのもあるけど)
Avatar
omochimetaru 10/3/2017 2:04 AM
—> MI<2>: {0, 1}, where 1 + 1 = 0. —> MI<3>: {0, 1, 2}, where 1 + 1 = 2, and 2 • 2 = 1 —> ... and so on.
2:04 AM
DependentTypeってGenericsのところに値を入れられる概念のことかな
2:05 AM
don’t we need something like this for Fixed Size Arrays™ too?
FixedArray<3> とかも言及されてる
Avatar
C++み
2:06 AM
欲しい場面は結構ある
Avatar
omochimetaru 10/3/2017 2:06 AM
だから @taketo1024 さんがiOSDCでも Depdendency Type が欲しいって言ってたのかな。
2:06 AM
「ある多項式で除算した体の空間」みたいなアレが型にできるんか
Avatar
行列とか、これ有るのと無いのとでは世界が違う
2:06 AM
それ出来るね
2:07 AM
今はなんか、次数を限定して、struct _1, _2, _3...と作ってextension大量に生やして誤魔化せば、それっぽい物が作れるなぁ、ぐらい
Avatar
omochimetaru 10/3/2017 2:10 AM
そのアプローチだと 加算とかは作れるけど、 == とかが作れなそう
2:11 AM
Equal<_1, _1> == _1 Equal<_2, _2> == _1 Equal<_1, _0> == _0 (edited)
2:11 AM
こういうことができないと型で構成した数の中で繰り返し計算とかができないから
2:11 AM
掛け算の結果とか除算の結果とかひたすら無限に全部の組み合わせを定義することに
2:12 AM
ん、足し算すら無理か?
Avatar
そうそう、無限に定義しなきゃいけないよ
Avatar
omochimetaru 10/3/2017 7:43 AM
eventually we will have something like the current @_versioned attribute, where internal (or even private, as some have suggested) functions can be “public ABI”. For example, @_versioned func myInternalDetails() { // … } @inlinable public func myPublicFunction() { myInternalDetails() // I can reference this from an inlinable function, but users can’t call it directly }
7:44 AM
やっぱり現状の@_versionedをつけた関数はインライン可能関数の中から呼べるらしい
7:44 AM
publicになったわけではないから直接は呼べない
Avatar
omochimetaru 10/3/2017 7:52 AM
versionedについての記述見つからず。。 インライン可するときのバージョンを記録しておいて、 ライブラリが更新されたときに、リンクしてるそれが変更されたことを検知できるようにするとか、そういう意味でこの名前かな
Avatar
let data = (0..<2*3).map { UInt8($0) } let a = data.map { $0 + 1 } let b: [UInt8] = data.map { $0 + 1 } /swift-execution/Sources/main.swift:3:32: warning: '+' is deprecated: Please use explicit type conversions or Strideable methods for mixed-type arithmetics. let b: [UInt8] = data.map { $0 + 1 } ^ Strideable+(UInt8, Int)との絡みだと思いますがなぜbだけ警告されるんでしょう?
Avatar
警告出なかった・・・
Avatar
あれ?
Avatar
swiftc で。
7:02 AM
$ swift --version Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36) Target: x86_64-apple-macosx10.9
Avatar
swift sandboxでSwift4では出てます。 Xcode9でももちろん出ててます
7:03 AM
たしかにswiftcだと出ないですねぇ
Avatar
謎だね
Avatar
playgroundsでも出ないですけどこれはもともとそういうもんなんでしたっけ?
Avatar
REPLとかPlaygroundsは色々違いそう
Avatar
norio_nomura 10/4/2017 7:49 AM
Swift 3.1.1だと再現する。Swift 4.0だと再現しない。
Avatar
Protocol oriented Integer入ったら再現しなくなる?
Avatar
あーxcodeのほう3.2に設定されてました。
Avatar
ひどいw
Avatar
swift sandboxのほうはなんだろう?
Avatar
An interactive website that lets you write, execute, and share Swift code in a server environment – on top of Linux!
7:58 AM
これ?
7:58 AM
Swift Ver. 3.1.1 (Release)
Avatar
4.0選べますよ
Avatar
たしかに4でも出る
Avatar
sandboxとXcodeのSwift4がバージョン違うのでは…
Avatar
単純にそれですかね
Avatar
もしかしてLinuxだと出るとか?
8:02 AM
出なかった
8:02 AM
$ swift --version Swift version 4.0 (swift-4.0-RELEASE) Target: x86_64-unknown-linux-gnu
8:02 AM
$ swift --version Swift version 4.0 (swift-4.0-RELEASE) Target: x86_64-unknown-linux-gnu
8:03 AM
Sandboxなんでリリース版じゃないんだ・・・ Swift Dev. 4.0 (Sep 5, 2017)
8:03 AM
IBMやる気なくなってきたのかな・・・
Avatar
ンゴw
8:03 AM
キトラで天下取れないと踏んだんですかね
🤔 1
Avatar
Latest 選択すると 3.1.1 になるし
Avatar
releaseまでに修正されたんですねぇ
Avatar
わずかな間だね、Sep 5だと。
Avatar
omochimetaru 10/4/2017 8:06 AM
IBMSwift、4系の選択がなかなか増えなくて最近不便。
Avatar
普通にBluemixをアップデートするのが大変で止まってるだけかも
8:07 AM
Google App Engine とかずっと Java 7 / Python 2 系で止まってたし
Avatar
omochimetaru 10/4/2017 8:08 AM
Java7やPy2のノリでSwift3が延命しないでw
Avatar
Appleは容赦なく切り捨てるけど、IBMはAppleじゃないからw
8:09 AM
Apple界隈、開発者がよく訓練されてて、みんなすぐに最新に追従するのすごいと思う。
Avatar
古いバージョン使ってると文字通り人権無くなりますからね
Avatar
RxSwift4もSwift3.x丸ごとバッサリ切ってて笑う
Avatar
まさに今日僕のライブラリもSwift3切ってたらクレームがw
8:11 AM
おっと、そろそろ Mobile Act に出かけないと。↓で Swift と Kotlin について話してきます。 https://mobileact.connpass.com/event/65935/
# 開催概要 Mobile Act OSAKA はフェンリル大阪メンバーが開催するモバイルアプリ開発勉強会です。 「関西でモバイルアプリ開発関連の情報共有や交流の機会をもっと増やしたい」という思いから、勉強会を開催させていただくこととなりました。 フェンリルでは、1年ほど前から名古屋メンバーによって Mobile Act NAGOYA を開催してきました。今回の大阪での勉強会開催にあたり、同じ Mobile Act の名を冠して実施したいと思います。 Mobile Act OSAKA は今後も継続的に開催していく予定です。今回はその第1回となります。 # 発表者募集 5分間の...
👀 1
Avatar
旧バージョン使ってな^^と返しましょう
Avatar
norio_nomura 10/4/2017 8:11 AM
あーxcodeのほう3.2に設定されてました。 Swift 4.0のREPLに-swift-version 3をつけても再現しなかった。
Avatar
REPLはwarningが違うことがあるような気がしてますがそんなことないですっけ?
8:13 AM
たとえば(当然ですが)↓だとwarning出ないですし。 Welcome to Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36). Type :help for assistance. 1> let a = 42 a: Int = 42
Avatar
norio_nomura 10/4/2017 8:14 AM
Swift 3.1.1だとエラーになります。 $ docker run --privileged -it --rm norionomura/swift:311 swift -I /usr/lib/swift/clang/include Welcome to Swift version 3.1.1 (swift-3.1.1-RELEASE). Type :help for assistance. 1> let data = (0..<2*3).map { UInt8($0) } 2. let a = data.map { $0 + 1 } 3. let b: [UInt8] = data.map { $0 + 1 } error: repl.swift:3:32: error: ambiguous use of operator '+' let b: [UInt8] = data.map { $0 + 1 } ^ (edited)
Avatar
swift sandboxでもそれは確認してました。 swift3.2もリリース前に同時に修正されたんじゃないでしょうか
Avatar
norio_nomura 10/4/2017 8:16 AM
元はwarningなので、正確には再現できていないですね。
Avatar
ん?でも修正されてるならxcodeで出てるのがおかしいのか
Avatar
norio_nomura 10/4/2017 8:38 AM
IBM Swift SandboxのDev. 4.0 (Sep 5, 2017)の挙動は、swift-4.0-DEVELOPMENT-SNAPSHOT-2017-09-05-a付近の挙動とも違う。 (edited)
8:41 AM
あいや、あってるか。
8:45 AM
-swift-version 3つけてもREPLだと出ない。-swift-version 3つけててソースをファイルから読み込んだ時だけwarningが出る。macOS, Linux共に。
1:13 AM
モジュール跨ぎインライン化のスレが伸びてる
1:14 AM
ラトナが @inlinable じゃなくて @fragile にしようって言ってて
1:15 AM
@fragile は struct の方のスレでも出てきてて、キーワード増やさないほうがいいし、って言ってるんだけど
1:16 AM
全然違う話に見えるし同じキーワードになる意味がようわからん
1:17 AM
あと @_versioned が付くと private でも 見えるようになるらしいんだけど
1:17 AM
このままだとライブラリ作者が @inliable と @_versioned を付けまくる未来になりそうで
1:17 AM
むしろその2つデフォルトでいいんじゃないかと思うんだけどそういう話題は無し
Avatar
それデフォだと何か問題あるんですかね?ビルド時間?
Avatar
omochimetaru 10/5/2017 1:18 AM
コンパイル時間が増えるのとバイナリサイズが増えるのがあるはず
1:19 AM
でも @inlinable は「必ずインライン化しろ」って意味でも無いんだよなあ
1:19 AM
@inlinable な関数自体はユーザモジュールごとにコンパイルされて実体を持つけど それが更に呼び出しユーザのところにインライン展開されるかどうかはその先のコンパイラの判断っぽいような。
Avatar
バイナリサイズはそんなに増えるんですかね? 手動スペシャライズするよりはましに思えますが
1:20 AM
ユーザー側の話かな
Avatar
omochimetaru 10/5/2017 1:20 AM
そもそも手動スペシャライズは用意した型にしかできないでしょ
Avatar
そうですね
Avatar
omochimetaru 10/5/2017 1:20 AM
Obsevable<Int> とかみたいに
1:20 AM
ジェネリクスが絡むと型の種類数は無限にあるから
1:21 AM
ユーザ定義型ももちろんだけど
Avatar
デフォルト @inlinable でいいと思うけどなぁ。
Avatar
omochimetaru 10/5/2017 1:22 AM
1:24 AM
@inlinable @_versioned がデフォルトでついててよくて ソースを見せないための @hiddenSource みたいな指定があったらいいような気がする
Avatar
まあオープンソースじゃなかったらその @hiddenSource を付けまくることになるか?
Avatar
omochimetaru 10/5/2017 1:25 AM
まとめて指定する方法は欲しそうですよね
1:25 AM
コンパイラオプションでモジュールレベルでやるとか。
1:25 AM
それだとちょっとしたミスでソースが流出しそうで微妙かな・・・
1:30 AM
C++のビルドが遅いのは具象化されるからなのか、それともテンプレート展開のSFINAEテクニックでの分岐が多すぎるからなのか
1:30 AM
後者が重い気がしてて前者は本質じゃないと思ってて、それならビルドはいけそうだよなあ
Avatar
うーん、モジュールまたぐときだけの話だからデフォルトじゃなくていい気がしてきた。
Avatar
omochimetaru 10/5/2017 1:36 AM
結構言及されちゃってるけど @_versioned は次スレでって事になってるし
1:36 AM
@_versioned のほうのデフォルト化の話はするとしたらそのときか
Avatar
omochimetaru 10/5/2017 2:32 AM
extensionの中のprivateって実質 file private なんですね
2:32 AM
extension Cat { private func f() -> Int { return 333 } func bb() -> Int { return f() } } extension Cat { private func f() -> Int { return 555 } func cc() -> Int { return f() } }
2:32 AM
↑これワンファイルだとf() が衝突してコンパイルできないけど、それぞれ別ファイルにすると動く
Avatar
それは確か、privateのスコープ変更するよ〜〜って奴では
Avatar
omochimetaru 10/5/2017 2:33 AM
これもその話?
Avatar
extensionのprivateはCatの外からは触れないと思うよ
Avatar
その同じファイルに定義した別の型からは見えないんじゃない?
Avatar
omochimetaru 10/5/2017 2:33 AM
あ〜
Avatar
たるのんが言ったのと同じ
Avatar
omochimetaru 10/5/2017 2:34 AM
fileprivateなら同じファイルの中からなら見えるはずだからってことか
Avatar
fileprivateならみえる
Avatar
omochimetaru 10/5/2017 2:34 AM
じゃあfileprivateではないけど
2:34 AM
ファイルをわけないとだめってことは、型の中でfileprivate的な感じ?
2:35 AM
いや、ちがうのか privateはつねにファイルの中からしか見えない・・・?
Avatar
privateは同一スコープ+同じファイルにある同じ型 から見えると思ってるけどちがうかな
Avatar
omochimetaru 10/5/2017 2:37 AM
いまためしたけどそうっぽい
2:37 AM
クラス本体のprivateは別ファイルのextensionから見えない
2:37 AM
同じファイルのextensionは
2:37 AM
あーいける
2:37 AM
なるほど
Avatar
本当にextensionの中だけで使うprivateにしたければファイル分けろって感じかね
Avatar
privateの定義が「同ファイルの同型のスコープ内」に掛かってる。swift4から
Avatar
omochimetaru 10/5/2017 2:38 AM
さっきのinlinableスレで言及されてるんだけど
2:38 AM
privateなメソッドはファイル名を含むシンボルにコンパイルされてるんだとさ
Avatar
Private access restricts the use of an entity to the enclosing declaration, and to extensions of that declaration that are in the same file.
Avatar
omochimetaru 10/5/2017 2:41 AM
なるほどねえ
Avatar
_TA2HelloFprivateMethod ファイル名含むシンボルってこげな奴でしょ、見る見る
Avatar
任意のenumがあるときに、特定のケースのassociatedvalueを取り出したい enum Some { case foo(Foo) case bars([Bar]) case piyoOrNil(Piyo?) } func getBars(from: Some) -> [Bar]? { /* ??? */ } このOptionalへの変換、サクッとする方法ないですよね、 if case .bars(let x) = from { return x } else { return nil } switch x { case .bars(let x): return x; default: return nil } ↑しかない。
Avatar
omochimetaru 10/5/2017 5:58 AM
無いから Someにextensionで bars: [Bar]? を生やすかな
Avatar
だよなー
5:58 AM
gybの出番か
Avatar
omochimetaru 10/5/2017 5:59 AM
手で書いたほうが早そう
Avatar
いや、この手のenumを無数に作る事を考えていて
Avatar
omochimetaru 10/5/2017 5:59 AM
switch - case - default だし。
5:59 AM
無数w
Avatar
毎回やるのは苦痛すぎる
Avatar
omochimetaru 10/5/2017 6:00 AM
Unionタイプが欲しかった系の感じがする
Avatar
enum-convertibleでもいいかな
6:00 AM
でもfoo.case0とかで生えててもあんま嬉しくないなぁ
6:01 AM
可読性ゴミだ
Avatar
omochimetaru 10/5/2017 6:01 AM
ああ
6:01 AM
gybのいいところはそういうところでシンボル名生成できるところだよな
6:01 AM
ジェネリックなライブラリでやろうとしても hoge0 hoge1 ... って用意しておくしかない
Avatar
gybじゃないなぁ
6:02 AM
なんかソースコード中にあるその目的のEnumを抽出して勝手にExtension生成してほしい
6:02 AM
静的解析+コード生成か
Avatar
Sourceryとかのほうが相性良さそう
❣ 1
Avatar
良いものないすかね
6:03 AM
いけそう
Avatar
本質的にやりたいのは、モナドの中のenumに対して外側でswitchが使いたいという欲求だった
Avatar
enum MyEnum { case case1 case case2 case case3 } let e = Optional<MyEnum>.some(.case1) switch e { case .some(.case1): print("case1") case .some(.case2): print("case2") case .some(.case3): print("case3") case .none: print("none") }
6:34 AM
こう?
Avatar
Optionalはそれが出来る
6:34 AM
ArrayとかObservableでは出来ない
Avatar
omochimetaru 10/5/2017 6:34 AM
実装がenumになってるモナドならできるね
Avatar
つまりー
Avatar
omochimetaru 10/5/2017 6:34 AM
だいたいは .map { switch ... } とか .flatMap { switch ... }
6:35 AM
だよね
Avatar
そうそう
6:35 AM
でもそれすると、switchの網羅性が消滅するので
6:35 AM
外側でやりたいという欲求があった
6:35 AM
さっきのOptional変換は、flatMapにOptional食わせればいいやというワークアラウンドなのだけど、そこ楽になっても網羅性保証出来ない
Avatar
omochimetaru 10/5/2017 6:35 AM
ん? stream.map { switch $0 { } } は $0はMyEnum なら網羅性は残ってない?
Avatar
ほしいのはそれぞれのassociatedvalueの型のモナドなので
Avatar
omochimetaru 10/5/2017 6:37 AM
あーなんとなくわかった
Avatar
let c0s = stream.flatMap { $0.case0 // Case0? } let c1s = stream.flatMap { $0.case1 // Case1? } ... 多分こうなる
Avatar
omochimetaru 10/5/2017 6:38 AM
enum Value { case .int(Int) case .str(String) } で、 Array<Value> から Array<Int> になったり Array<String> になったりしたい?
Avatar
そう
6:38 AM
Array<Int>とArray<String>、それぞれの処理を書いてないとコンパイルエラー
Avatar
omochimetaru 10/5/2017 6:38 AM
extension で Value に .intValue を生やしてやれば、その実装をするときには網羅性が効いてうまくいく? (edited)
Avatar
いや
6:39 AM
駄目だと思う
6:39 AM
Array<Value>自体がEnumっぽく振る舞えばいけそう
Avatar
omochimetaru 10/5/2017 6:39 AM
あーーー
Avatar
えーっと本質的にはなんだ
Avatar
omochimetaru 10/5/2017 6:40 AM
その続きを分岐して書きたいのか
Avatar
Enumの外と内を分解して入れ替えたい
Avatar
omochimetaru 10/5/2017 6:40 AM
Intの場合だけ続きを書きたいんじゃなくて。
Avatar
Array<Either<A, B, C>> -> Either<Array<A>, Array<B>, Array<C>>
6:40 AM
こうだ
Avatar
omochimetaru 10/5/2017 6:40 AM
なるほど
Avatar
これやりたいならenum-convertibleが一番良い気がしてきた
Avatar
omochimetaru 10/5/2017 6:41 AM
そう考えるとenumをswitch-caseで分岐してるときって
6:41 AM
その分岐コンテキストをモナドとして値に保持できないから
6:41 AM
try-catchにResultが無いのと同じように
6:42 AM
switch-caseにも対応するモナドが無いんだな
6:42 AM
だから外側と内側を入れ替えたデータ構造を簡易に構成できない(その場でswitch-caseのフローを書き下すまでしかできない)
Avatar
やりたいことが見えてきてしんどくなってきた(´・ω・`)
Avatar
omochimetaru 10/5/2017 6:43 AM
このEither<Array<A>, Array<B>, Array<C>> を case0 みたいな味気ない名前じゃなくやりたいねえ
Avatar
extension Observable where E: EnumConvertibleX { func sequence() -> EnumX<Observable<E.Case0>, Observable<E.Case1>, ....> } こうか~~~
6:45 AM
これがあると
6:46 AM
es.bind { (es) -> Disposable in switch es.sequence() { case .case0(let c0s): return c0s.subscribe(c0sTarget) case .case1(let c1s): return c1s.subscribe(c1sTarget) case .case2(let c2s): return c2s.subscribe(c2sTarget) ... } } .disposed(by: db) こんな感じになるかな (edited)
6:48 AM
RxSwiftのbindがネストできたの忘れてた
6:50 AM
Sourceyで自動生成しようとすると、MyEnumに対してMyEnumArrayとかMyEnumObservableみたいなのを生成することになる
6:50 AM
それはそれで良いのかもしれない
6:51 AM
ん…?なんかおかしい気がしてきた
6:51 AM
ArrayもObservableも中身を配分するんだからswitchじゃねーな
Avatar
2つのprotocolを同時に実装するときに、両方のassociatedtypeの名前がかぶってると、それぞれを違う型で埋めることって一切出来なくなりますよね
5:04 PM
protocol A { associatedtype X func fa(_ x: X) } protocol B { associatedtype X func fb(_ x: X) } class C: A, B { // できない func fa(_ x: Int) { } func fb(_ x: String) { } }
Avatar
できないですね。
Avatar
typeerasure作ってAConvertibleとBConvertible作るしか無いか…
7:19 AM
AnyHogehogeパターンで ジェネリックメソッドの部分ってどうすればいいんだろ?
7:20 AM
↑のソースでいう _cast のところがうまく書けない
7:25 AM
/Users/omochi/temp/swany/Sources/swany/main.swift:31:15: Cannot invoke 'cast' with an argument list of type '(to: (Any.Type))' /Users/omochi/temp/swany/Sources/swany/main.swift:31:15: Expected an argument list of type '(to: T.Type)'
Avatar
あー
7:28 AM
これ面倒くさそう
Avatar
omochimetaru 10/6/2017 7:28 AM
何か見落としてる凡ミス?それともこの川・・・深いっ?
Avatar
かわいそうだけど
7:29 AM
型パラを持つクロージャは作れない。の制約があって
Avatar
omochimetaru 10/6/2017 7:29 AM
まあ、それはそうだよね 変数に保持する時点で<T>が露出しちゃうし
Avatar
このままだと駄目なので
Avatar
omochimetaru 10/6/2017 7:29 AM
<T>が決まるのは呼び出しのたびだし
Avatar
ちょっとしたワークアラウンドがあったはず
7:29 AM
あれ、できるか?
Avatar
GitHub is where people build software. More than 24 million people use GitHub to discover, fork, and contribute to over 68 million projects.
7:37 AM
String.Type nil
7:38 AM
Any.Type じゃなくて String.Type ってでるのは existential だから??
Avatar
実行時に型パラ渡す方法が無いから無理っぽい
7:40 AM
ええーっと
7:40 AM
これあれだ
7:40 AM
GenericsパラメータにProtoocl.self入れられない問題でハマる
7:40 AM
Anyがprotocolだから無理
Avatar
omochimetaru 10/6/2017 7:44 AM
でもこれやりたいんだよね
7:44 AM
クラスや継承でやっているパターンを
7:44 AM
structとprotocolとTypeErasureでやろうとしたときに
7:45 AM
as! でのダウンキャストに相当する部分が残ってしまって
7:45 AM
それがこの func cast<T>() なんだよね
Avatar
cast式をProtocol内部に書かなきゃいけない理由は?
Avatar
omochimetaru 10/6/2017 7:53 AM
Any で保持して as? でキャストするアプローチだと
Avatar
//global func cast<T: CatProtocol, U: CatProtocol>(from: T, to: U.Type=U.self) -> U?
7:53 AM
こう
Avatar
omochimetaru 10/6/2017 7:53 AM
AnyCat が AnyCat を包んでいる場合とかで穴があく
Avatar
AnyCatのcastを種から生成したい、か
7:56 AM
castメソッドだけ existential が使えるprotocol に切り分けたら 一応いけた
7:57 AM
でもこれだとあれだね、 「ジェネリック かつ (associatedtype または Self) が絡む func」には対応できない (edited)
Avatar
associatedtype が無いなら、素直に内包すれば良いと思うんだけど、そういう話ではない? (edited)
Avatar
omochimetaru 10/6/2017 7:59 AM
private var base: CatProtocol ↑これできます? clone() -> Self があるけど
Avatar
assoctype持つ場合は無理、が解決できないのが厳しい
Avatar
omochimetaru 10/6/2017 7:59 AM
あれ、いけるな
8:00 AM
Selfはあってもいいのか。
Avatar
AnyCat1(base.clone()) が必要だけど。
Avatar
omochimetaru 10/6/2017 8:02 AM
素直に内包すれば良い
var base 方式とクロージャ方式の特性について調べていたので
8:02 AM
これはこれでそれだけの話かもしれません
8:02 AM
Selfが絡むとvarにできないと思ってたけどできますね。associatedtypeがある場合が問題か。
8:03 AM
Selfが絡むとダメだった記憶あるけどなんだったっけ・・・
Avatar
Equatable?
Avatar
omochimetaru 10/6/2017 8:04 AM
protocol Eq { func eq(_ x: Self) -> Bool } func f(_ a: Eq, b: Eq) -> Bool { return a.eq(b) } /Users/omochi/work/playground/TempGround.playground:5:13: Protocol 'Eq' can only be used as a generic constraint because it has Self or associated type requirements
8:04 AM
本当だ。
8:05 AM
protocol Eq { func eq1() -> Self func eq2(_ x: Self) } func f(_ a: Eq) { }
8:05 AM
eq1はあってもOK、eq2があるとダメ
Avatar
サブクラス方式なら associatedtype の問題は解決できるかな?
8:10 AM
associatedtype つけてみました。 CastProtocol 方式ならまだいける
Avatar
CastProtocol側がassoctypeで汚染されないおかげで変数として確保出来るから
Avatar
omochimetaru 10/6/2017 8:12 AM
これでまだ解決しないパターンは、 func cast みたいな ジェネリックメソッドそれ自体が associated type の絡んだシグネチャを持つことか
Avatar
ところで castはデフォルト引数あったほうが <T>(_ type: T.Type=T.self) -> T? (edited)
8:13 AM
左右どちらからも型推論出来るようになってお得です
Avatar
omochimetaru 10/6/2017 8:13 AM
ああ、たしかに。出たその技
Avatar
お得だけど、protocolの宣言でデフォルト引数書けないのがつらいですね
8:14 AM
かきたい
Avatar
omochimetaru 10/6/2017 8:17 AM
func difficult<T>(to: T.Type, food: Food, me: Self) -> Self
8:17 AM
追加した。どうすんだこれ。
Avatar
omochimetaru 10/6/2017 8:31 AM
func difficult1<T>(to: T.Type, food: Food)
8:31 AM
これだけで無理みがある
Avatar
omochimetaru 10/6/2017 8:50 AM
すげえ
Avatar
とっくに諦めてたのにすごい執念だ・・・
Avatar
omochimetaru 10/6/2017 8:52 AM
あれえ・・・シンプルすぎて何がどうなってるのかわからん・・・
8:52 AM
いったんclassでBox作ったのがポイントか・・・?
Avatar
assoctypeをGenerics型に閉じ込めたところですかね
Avatar
omochimetaru 10/6/2017 8:55 AM
AnyCatBox<Base: CatProtocol> ここか・・・
8:57 AM
これってAnyCatBaseとAnyCatBoxの2つ必要なんです?
8:57 AM
いま自分でもいじってるけど
Avatar
必要、Generics型にAssoctypeを閉じ込めるという必要がある
Avatar
omochimetaru 10/6/2017 8:58 AM
あーFoodが焼いてあるのか
Avatar
そこを書き換えるのにoverrideもいる
8:58 AM
これ似たようなことstdlibでもやってるんですか?
Avatar
AnySequence とかはこの方式ですね。
Avatar
omochimetaru 10/6/2017 8:59 AM
これマスターしないとSwift書けねえな
😂 1
Avatar
Sequenceのmapどうやってんだって考えてて、じゃあ中身はClassとか詰まってるんですね
Avatar
ちょっと実行速度遅いですけど。
Avatar
純粋値型Swiftの実態は涙ぐましいclassを使ったworkaroundですっていうのが現代御伽噺
Avatar
omochimetaru 10/6/2017 9:04 AM
あーなるほど・・・
9:04 AM
var _box: AnyCatBase<Food> の時点では捕まえるCatProtocolの真の型がわからないからこれが必要で
9:05 AM
initで<Base> が来て初めてそこでサブクラスのジェネリクスのとこに焼きつつ代入して保持するのか
Avatar
パターンは覚えたので次から使えるぞ、やったぜ
Avatar
omochimetaru 10/6/2017 9:07 AM
まだ咀嚼できてない
Avatar
@tarunon
純粋値型Swiftの実態
純粋値型Swiftはexistentialもtype erasureも許さないので問題なしです👍むしろ、こういうややこしい問題をなくしたいから使いたくないって感じですね。
Avatar
omochimetaru 10/6/2017 9:10 AM
わかってきた
Avatar
1. Protocolにあるassociatedtypeを全部型パラに詰めたClass(A)にassociatedtypeが関わる関数を全て実装、中身は空でOK 2. Protocolを型パラに取るAのサブクラスBを実装、プロパティに型パラのProtocol、Aの型パラと全部結びつけてすべての関数をOverride 3. TypeErasureにAのプロパティを置いてBを代入しその関数を呼ぶ。 (edited)
Avatar
omochimetaru 10/6/2017 9:11 AM
サブクラスに隠すところがコツだな〜
9:12 AM
ですねですね
9:16 AM
いやこれいいな、なんでも var base の形で保持できるわけだし
Avatar
ちょっとabstract class実装しないのん…ってなるけど、Generics manifestが完成したらabstract classは無用の長物になるのかしら
Avatar
omochimetaru 10/6/2017 9:25 AM
struct + protocolでいけるから?
Avatar
そう
Avatar
omochimetaru 10/6/2017 9:26 AM
たしかに・・・?
Avatar
https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials これさえあれば型消しいらなくなるし、classもそこまで重要なものでもなくなると思っていて
swift - The Swift Programming Language
9:27 AM
少なくともどうしてもabstract classじゃないと駄目なんだ!っていうのはほぼ無くなると思う
Avatar
omochimetaru 10/6/2017 9:28 AM
% for Kind in ['Sequence', 'Collection', 'BidirectionalCollection', 'RandomAccessCollection']: extension Any${Kind} {
9:28 AM
めちゃくちゃ無理やりでワロタ
Avatar
めちゃくちゃしやがる
Avatar
omochimetaru 10/6/2017 9:28 AM
検索しづらいから こう書いて欲しいンゴね % for Kind in ['AnySequence', 'AnyCollection', 'AnyBidirectionalCollection', 'AnyRandomAccessCollection']: extension ${Kind} {
Avatar
Kindってそこ以外で使われてないの?
9:29 AM
この20行の範囲に Any${Kind} がたくさんでてくる
9:30 AM
かならず Any${Kind} の形で出てきてるように見えるね。
Avatar
Swift側でKindだけほしいケースがないので
9:30 AM
PRチャンスでは?
Avatar
omochimetaru 10/6/2017 9:30 AM
これの修正?w
Avatar
検索ビリティが低いぞって言って暴れる
9:30 AM
いやーやらないな
Avatar
omochimetaru 10/6/2017 9:31 AM
う、うーんw まあ益はあるのか・・・?
Avatar
omochimetaru 10/6/2017 9:51 AM
class _AnySequenceBox<Element> { internal func _makeIterator() -> AnyIterator<Element> { _abstract() } } final class _SequenceBox<S> : _AnySequenceBox<S.Iterator.Element> { internal override func _makeIterator() -> AnyIterator<Element> { return AnyIterator(_base.makeIterator()) } } struct AnySequence<Element> : Sequence { public init<S : Sequence>(_ base: S) where S.Element == Element { self._box = _SequenceBox(_base: base) } internal let _box: _AnySequenceBox<Element> }
9:51 AM
さっきの @rintaro さんのパターンと同じ構造なのを確認した。
9:51 AM
学びがあった・・・
9:52 AM
おまけ internal func _abstract( file: StaticString = #file, line: UInt = #line ) -> Never { fatalError("Method must be overridden", file: file, line: line) }
Avatar
便利
Avatar
KeyedEncodingContainer, KeyedDecodingContainerとかも同じ仕組み。 https://github.com/apple/swift/blob/master/stdlib/public/core/Codable.swift#L422
swift - The Swift Programming Language
Avatar
本当だ。 こいつはAny的な名前じゃないんですね。そしてプロトコルの方にはProtocolサフィックスがついてる。
Avatar
UnkeyedEncodingContainer, UnkeyedDecodingContainerと名前に一貫性を持たせるためですね。
Avatar
norio_nomura 10/7/2017 2:41 AM
Standard LibraryがRecursive Protocol Constraintsを使った実装になって最初のスナップショット swift-DEVELOPMENT-SNAPSHOT-2017-10-06-a が出てる。
Avatar
Swift 4 の Numeric で EasyImagy の自作 NumericType から解放されると思ったら ExpressibleByIntegerLiteral 付いてて使えない・・・
3:36 AM
ほしいのはもっとシンプルに「群・環・体」みたいなプロトコルなんだけどなぁ。
3:36 AM
どうも、佐野です。前回の記事 で整数は「環」、有理数・実数・複素数は「体」であるという話をしました。今回は「群・環・体...
Avatar
omochimetaru 10/7/2017 3:36 AM
それがついてるとなんでダメなんですか?
Avatar
たとえば RGBA に対して Numeric を適用する場合、整数リテラルから生成できるようにしないといけなくなる・・・
Avatar
omochimetaru 10/7/2017 3:37 AM
RGBA型を、ですか?
Avatar
今 + が定義されていることを保証したいだけなので Numeric が過剰すぎる・・・
3:38 AM
うん。 RGBA 同士の足し算ができるようにしたい。
Avatar
omochimetaru 10/7/2017 3:38 AM
なるほど、たしかにそれは変だ
3:39 AM
Inherits From Equatable, ExpressibleByIntegerLiteral
Avatar
omochimetaru 10/7/2017 3:39 AM
0xFf000000から
3:39 AM
8bitずつRGBAを読み取る、とか、
3:39 AM
稀にあるけどw
Avatar
RGBA<T> とかもあるし
Avatar
omochimetaru 10/7/2017 3:40 AM
どんどん無理になるな
Avatar
↑は今回の話とは別にリテラル導入すると便利かどうかで検討したけど保留中で、 Numeric のために導入するのはあきらかに手順がおかしいw
3:41 AM
せっかく自作 UnboundedRange から解放されて次は Numeric だと思ったのに・・・
3:47 AM
Associated Types に Index がない・・・。型が _ プレフィックスとかかな? https://developer.apple.com/documentation/swift/collection
3:48 AM
あれ?普通だ。なんでリファレンスから漏れたんだろう?
Avatar
omochimetaru 10/7/2017 3:49 AM
肝心のstartIndexがなくなあ?
3:49 AM
なくない?
3:49 AM
型もないけど
Avatar
ほんとだ
3:50 AM
Swiftのリファレンス使い物にならないな・・・
Avatar
omochimetaru 10/7/2017 3:50 AM
基本役に立たないよねw
3:51 AM
ソース見る > Xcodeから飛ぶ > ドキュメント見る
Avatar
メソッドの戻り値が一覧で省略されてるのとか、型パラメータが下までスクロールしないと出てこないのとか
Avatar
norio_nomura 10/7/2017 7:37 AM
Collection.Indexとか startIndex とかは swift-DEVELOPMENT-SNAPSHOT-2017-10-06-a でようやく Jump to Definition 先で見られる様になりました。
7:38 AM
それ以前は、Recursive Protocol Constraintsがなかったせいで非公開のプロトコルで定義されていました。
7:39 AM
ドキュメントはそれを元に生成されているらしく、それらは未記載。
Avatar
omochimetaru 10/7/2017 7:41 AM
そういうことなんですね
Avatar
なるほど
Avatar
/Let it be/ func() -> @discardable Bool {} /Rather Than/ @discardableResult func() -> Bool {}
このスレわろた
2:03 AM
func() -> @discardable Bool func getBool() → async Bool func foo() -> discardable Bool func x() -> Bool @ throws disguardableResult public async mutating public async mutating throwing func foo() -> discardable Bool
2:03 AM
一つ目のやつがスレの提案で、これも関数名の打ち忘れでカオスなんだけど
2:04 AM
便乗して他の人が他の話してて
2:04 AM
4番はひどい
Avatar
asyncとthrowsは式の型で、他のアノテーションとか修飾子の類とは全然違うんじゃないの
Avatar
うん、async Bool に関しては、型だけの問題じゃなくて関数全体に影響する話だからそりゃ違うよって突っ込まれてる
Avatar
4番目のやつは
2:06 AM
なんか途中までの流れで、 @discardable が関数のほうに付くのはCっぽくてSwiftっぽくない
2:06 AM
って話に便乗して
2:06 AM
それでいうと名前の左側につけるもの全部右にすべき、みたいな。
2:07 AM
5番目のやつは4番目のやつに対して、 もっと英語っぽくしようぜ、って言って書いてる・・・・
Avatar
more Englishかな?ちょっとワロタ
Avatar
make it more English :) (edited)
2:07 AM
って書いとるね。
Avatar
var a: Int = 3 print(a) // 3 print(a is AnyObject) // true print(type(of: a) is AnyObject.Type) // false var b: AnyObject = a as AnyObject print(b) // 3 先週の型の互換性と is as の振る舞いが一致しない件、そういえばこんな例もある
4:01 AM
あとswiftにおける頻出がこれ var s: String = "" print(s is NSString) // true print(type(of: s) is NSString.Type) // false
Avatar
グエー
10:53 AM
この辺のキャストを全部Lintで弾くしか
10:53 AM
[Cat]を[Animal]に入れたらmap使えみたいな警告出したい
10:54 AM
let x: Int? = 1 も警告、.some使えと出てくる。
Avatar
as演算子がそのための明示的なオペレータなんじゃない?暗黙の変換と比べると。 as?と違って失敗しないわけだし
10:55 AM
.some()は暗黙だねw
Avatar
as明示で型が書き換わるなら、それはもう暗黙の変換してはいけないというのが
10:56 AM
自論なわけで、これに基づくとOptional, Arrayの共変性なんかは特に。
10:56 AM
明示でのみ書き換わるのは正義
Avatar
この間のヤバイキャストのバグ報告done https://bugs.swift.org/browse/SR-6126
Avatar
ww
10:06 AM
let a = x as Int?? let b = (x as? Int??)! let c = Int?.none as Int?? let d = (Int?.none as? Int??)! let e = (y as [Int??]).first! let f = (y as? [Int??])!.first! let g = ([Int?.none] as [Int??]).first! let h = ([Int?.none] as? [Int??])!.first!
10:06 AM
これは笑う
Avatar
網羅的にチェックしただけだよ
Avatar
とりあえずこれで回答出れば何が設計仕様で何が謎挙動なのかわかるね
Avatar
んだべな
Avatar
ウォッチ設定しとこ
10:08 AM
投票ってのはなんだ
Avatar
ところで僕が報告したIssue一個もクローズされなくて涙目なんだけど
10:08 AM
解決しろってプレッシャーかけるやつでは
Avatar
結果は気になるしポチっとこ
Avatar
efghの挙動見るに完全にバグなんだけど
10:09 AM
どっちを仕様として寄せるのか気になる
10:09 AM
Int? as Int?? が .noneになる世界なら俺はRustに移住するわ
Avatar
お、↑にコメントが。 Jordan Rose added a comment - 11 hours ago cc Joe Groff
Avatar
JordanRose氏、bugsに張り付いていて担当者を召喚してくれる人というイメッジがある
Avatar
トリアージ担当なのかな
Avatar
class Escaper { func take(_ f: @escaping () -> Void) {} } class Cat { var a: Optional<(() -> Void) -> Int> func f(escaper: Escaper) { a = { (handler: () -> Void) -> Int in escaper.take(handler) return 0 } } }
7:13 AM
Playground execution failed: error: TempGround.playground:4:26: error: passing non-escaping parameter 'handler' to function expecting an @escaping closure escaper.take(handler) ^ TempGround.playground:3:16: note: parameter 'handler' is implicitly non-escaping a = { (handler: () -> Void) -> Int in ^ @escaping
7:14 AM
プロパティで持ってる関数の型には @escaping がつけられないけど、それが、関数の引数になってる関数にも適用されるせいで、 関数からうけた関数をescapeすることができない・・・?
Avatar
class Escaper { func take(_ f: @escaping () -> Void) {} } class Cat { var a: Optional<(@escaping () -> Void) -> Int> func f(escaper: Escaper) { a = { (handler: @escaping () -> Void) -> Int in escaper.take(handler) return 0 } } } (edited)
Avatar
あれ、いけた
Avatar
@omochimetaru
プロパティで持ってる関数の型には @escaping がつけられないけど
プロパティで持ってるクロージャは @escaping のはず。
7:21 AM
そうじゃないとおかしい。
Avatar
そこまでやろうとしてうまくいかなかったけど別の問題にひっかかってたみたいでした。ありがとうございます。
Avatar
↓シンプルな例( lazy だから map@escaping 必須) struct Foo { var bar: (Int) -> Int } let foo = Foo(bar: { $0 * $0 }) [2, 3, 5].lazy.map(foo.bar) // OK
Avatar
あれ、新しいStringってIndexの型が混ざったの?
Avatar
Viewとは別にString自体がIndex持ってるべ
Avatar
typealias String.UTF8View.Index = String.Index typealias String.UTF16View.Index = String.Index
6:02 AM
ウオオ
6:02 AM
エンコード別のインデックスの型安全性はなくなってしまったのか
Avatar
ん、これどうやってエンコード別のindexみわけるの
7:28 AM
あーエンコード毎にIndex受け取ったときの処理が違うのか
Avatar
見分けられなくなったように見える。
7:29 AM
だから、String.Indexのコンストラクタで、第二引数で指定して、エンコード付きからString用に変換するんだけど
Avatar
あくまでIndexはpositionからのdistanceというだけの存在で、それを受け取ったView(或いはStringProtocolの具体型自身)がどうにか解釈すると
7:29 AM
もしかして
7:30 AM
String.*ViewもStringProtocol?
Avatar
init?(_ sourcePosition: String.Index, within target: String.UTF8View) https://developer.apple.com/documentation/swift/string.index/2922824-init (edited)
Avatar
ンンンw
Avatar
String.Index を扱うときに、それが、String 用なのか、 String.UTF8View 用なのか String.UTF16View 用なのか
7:31 AM
意識して扱わないといけなくて
7:31 AM
String.UTF8View 用の String.IndexString 用の String.Index に変換するのが↑のinit (edited)
Avatar
ん?意識する必要ありますか?utf8の中途半端な位置のインデックスを String につかっても、それなりの値は返ってくるとおもいますが。
7:54 AM
let str = "こんにちは!" str[str.utf8.index(str.startIndex, offsetBy: 0)] // こ str[str.utf8.index(str.startIndex, offsetBy: 1)] // こ str[str.utf8.index(str.startIndex, offsetBy: 2)] // こ str[str.utf8.index(str.startIndex, offsetBy: 3)] // ん
Avatar
outofrangeとか?そこはoptionalになるから問題ないのか
Avatar
out of rangeはすべてのViewで out of rangeになります。
Avatar
str[str.utf8.index(str.startIndex, offsetBy: 2)] これは動くってだけで、意味のないコードだと思いますけど・・・
7:57 AM
いや、あれ、ん???
7:57 AM
2回誤変換してるのか。
Avatar
str[str.utf8.index(str.startIndex, offsetBy: 2)] これを動くようにするのは議論の余地はあったんだと思うけど、0 と 3 がきちんと動くので、普通に使っている分には変換する必要がなくなったというだけだと思っています。 (edited)
Avatar
内側の、 utf8.index(_, offsetBy:) には String.UTF8View.Index を渡すべきだけど、 typelias だから String.Index も渡せちゃっていて、 外側の str[] には、 String.Index を渡すべきだけど、 typealias だから String.UTF8View.Index が渡せちゃっている
8:02 AM
3 がきちんと動く
これは、3バイト目へのアクセスとして使えてるってことですか? Stringの内部メモリがUTF8で保持さていることって保証仕様なんでしょうか
Avatar
いいえ、このインデックスが有効なのは、あくまで元の String が一緒の時だけです。
8:03 AM
Stringによって、バッファ上のバイト表現は違うので、 (edited)
8:06 AM
現在の String.Index はその String のバッファ上のバイトオフセット + α を持っている感じですね。
Avatar
Stringの内部メモリがUTF8で保持さていることって保証仕様
仕様が決まってるかはわからないけど実装はUTF16だった気が。
Avatar
いま確認していて一つ勘違いしていたのが、 utf8.index(_, offsetBy: 1) は、「1つ次のUTF8文字」に行くと思ってたけど、そうじゃなくて、1バイト進む、なんですね・・・
8:08 AM
let str = "こんにちは!" let u8str = str.utf8 u8str[u8str.index(u8str.startIndex, offsetBy: 0)] // 227 u8str[u8str.index(u8str.startIndex, offsetBy: 1)] // 129 u8str[u8str.index(u8str.startIndex, offsetBy: 2)] // 147 u8str[u8str.index(u8str.startIndex, offsetBy: 3)] // 227 u8str[u8str.index(u8str.startIndex, offsetBy: 4)] // 130 u8str[u8str.index(u8str.startIndex, offsetBy: 5)] // 147
Avatar
> 実装はUTF16だった気が ASCII で表現できる ときは ASCII のときもあると思いますよ。
Avatar
いいえ、このインデックスが有効なのは、あくまで元の String が一緒の時だけです。
なるほど。さっきのりんたろさんの例がどのように動作しているかはとりあえず理解できました。
8:11 AM
UTF8上でユニコードで1文字進んだ場所のバイトオフセットが知りたい場合は、unicodeScalarsのViewを経由してIndexを変換してくるべきなのか。
Avatar
let str = "𩸽だいすき!" let idx = str.index(str.startIndex, offsetBy: 1) str.utf8.distance(from: str.startIndex, to: idx) // 4 str.utf16.distance(from: str.startIndex, to: idx) // 2 str.unicodeScalars.distance(from: str.startIndex, to: idx) // 1 str.distance(from: str.startIndex, to: idx)
8:13 AM
> unicodeScalarsのViewを経由してIndexを変換してくるべきなのか。 変換という考え方を捨てて、View上でのIndexの位置を調べる、と考えると良いと思います。
Avatar
let str = "こんにちは!" let u8Str = str.utf8 let ucStr = str.unicodeScalars // ユニコードスカラとしての2文字目の位置のUTF8表現のバイト値を求めるコード let ucIndex2: String.UnicodeScalarView.Index = ucStr.index(ucStr.startIndex, offsetBy: 2) let strIndex2: String.Index = String.Index(ucIndex2, within: ucStr)! let u8Index2: String.UTF8View.Index = strIndex2.samePosition(in: u8Str)! let u8ByteOffset2: Int = u8Str.distance(from: u8Str.startIndex, to: u8Index2) print(u8ByteOffset2) // 6 print(u8Str[u8Index2]) // 227 <- 答え // 確認 print(str[String.Index(u8Index2, within: u8Str)!]) // に (edited)
8:17 AM
僕が「意識しないといけない」と思っているのは、 この、 strIndex2, u8Index2 への代入文の右辺の within:in: に、正しいものを入れないとちゃんと動かないからです
8:19 AM
あ〜
8:19 AM
変換という考え方を捨てて、View上でのIndexの位置を調べる、と考えると良いと思います。
8:21 AM
(String.Index と UTF8View.Index)、(String.IndexとUTF16View.Index)、それぞれの間での distance は正しく動く・・・?
8:23 AM
根っこのバイト表現上でのIndexになるから、 (UTF8View.IndexとUTF16View.Index) でも正しいってこと・・・?
Avatar
上げてもらった例でいうと、 let strIndex2: String.Index = String.Index(ucIndex2, within: str)! let u8Index2: String.UTF8View.Index = strIndex2.samePosition(in: str)! within: in: にどのViewいれても同じ結果になると思います。 (edited)
Avatar
within: in: にどのViewいれても同じ結果になると思います。
ほ、ほんとだ・・・
8:28 AM
public func samePosition( in utf8: String.UTF8View ) -> String.UTF8View.Index? { return String.UTF8View.Index(self, within: utf8) } public func samePosition( in utf16: String.UTF16View ) -> String.UTF16View.Index? { return String.UTF16View.Index(self, within: utf16) }
8:29 AM
oh...
Avatar
samePosition(in:) とかは、 let str = "こんにちは!" let u8Str = str.utf8 let ucStr = str.unicodeScalars let idx1 = u8Str.index(str.startIndex, offsetBy: 1) let idx2 = idx1.samePosition(in: ucStr) // nil こういうView間で完全に同一の位置の有無を調べるくらいしか用途ないんでないかな?
Avatar
within: が何かはやってるのか
8:32 AM
public init?( _ sourcePosition: String.Index, within target: String ) { guard target.unicodeScalars._isOnGraphemeClusterBoundary(sourcePosition) else { return nil } self = target.characters._index( atEncodedOffset: sourcePosition.encodedOffset) }
8:38 AM
let str = "こんにちは!" let u16Str = str.utf16 let u8Str = str.utf8 str[u16Str.index(u16Str.startIndex, offsetBy: 0)] let i1: String.Index = u16Str.index(u16Str.startIndex, offsetBy: 1) str[i1] // ん u8Str[u8Str.index(i1, offsetBy: 0)] u8Str[u8Str.index(i1, offsetBy: 1)] u8Str[u8Str.index(i1, offsetBy: 2)] let i2: String.Index = u8Str.index(i1, offsetBy: 3) print(str[i2]) // に
8:38 AM
なるほど・・・どうなってんだ・・・
Avatar
str.utf16でsubscriptは使えないの
Avatar
使えるけどUInt16だから→ u16Str[i1] // 12435
8:53 AM
u8Str[u8Str.index(i1, offsetBy: 0)] // 227
Avatar
internal init(encodedOffset o: Int, transcodedOffset: Int = 0, _ c: _Cache) { _compoundOffset = UInt64(o << _Self._strideBits | transcodedOffset) _cache = c }
9:03 AM
2bitシフトして、 (UTF16でのインデックス, 0...3) のタプルになっている
9:04 AM
現在のUnicodeが21bitでUTF8で4バイト文字までしか存在しないから
9:05 AM
UTF8での位置は、 UTF16でvalidな位置 + 0〜3のオフセット
9:05 AM
で、常に表現できるってことか?
9:06 AM
(ユニコードでの位置+UTF8ずらし分)的なデータ構造じゃないと辻褄が合わないと思ってて、こんなの出てきたからそうっぽいけど・・・
9:06 AM
extension String { /// A position of a character or code unit in a string. @_fixed_layout // FIXME(sil-serialize-all) public struct Index { @_versioned // FIXME(sil-serialize-all) internal var _compoundOffset : UInt64 @_versioned internal var _cache: _Cache internal typealias _UTF8Buffer = _ValidUTF8Buffer<UInt64> @_versioned internal enum _Cache { case utf16 case utf8(buffer: _UTF8Buffer) case character(stride: UInt16) case unicodeScalar(value: Unicode.Scalar) } } }
9:07 AM
String.Index型自体は内部に enum _Cache で、どの種類のビューのIndexなのかを保持しているから、適宜変換も可能と
Avatar
This post describes the goals, release process, and estimated schedule for Swift 4.1.
Avatar
Conditional Conformance は 4.1 で入らないのかな?
1:03 AM
The vast majority of sources that built with the Swift 4.0 compiler (including those using the Swift 3 compatibility mode) should compile with the Swift 4.1 compiler. ってことだけど、 Conditional Conformance が入ったら Countable 系の Range は不要になるので色々とソース互換性に影響が出そう。
Avatar
後方互換で残すのはあるのでは?
Avatar
Swift は後方互換よりも美しさ(?)を優先しているような印象があるけどなぁ。 (edited)
1:05 AM
typealias で残すとかはあり得る?
Avatar
Currently just removes restriction and adds some basic recording of conditionality, and feeds that information through to the GSB and constraint solver and anywhere else that needs it. This doesn't...
1:05 AM
作業は進んでるみたいですよ
Avatar
でも、それでも RangeCountaleRangeextension で同じメソッド生やしてたら衝突するからソース互換性はないな。 (edited)
Avatar
3.xでは大幅な切り捨てありましたっけ? Range は基本 ..< ばっか使ってるので Countable がなくなっても困らない可能性はある
Avatar
Semaは型推論とかのものが入ってるとこ
Avatar
huonw changed the title from [WIP] sema for conditional conformances. to sema for conditional conformances. 7 days ago
Avatar
オアズケか(´・_・`)
1:09 AM
assoctypeに自身を指定できる奴(SubSequenceのアレ)は流石に入るかな?
Avatar
↑の PR 、 WIP がとれたということは近々取り込まれるかもしれない?
Avatar
これが全てなのか関連作業が他にもあるのかはよくわかってない
Avatar
sema だけじゃなくて標準ライブラリの作業とかもありそう。
Avatar
たるのんのゆってるのはリカーシブプロトコルだっけ
1:10 AM
たしかに。
1:10 AM
過去のライブラリをめちゃめちゃ見直さないと。
Avatar
CodableArrayOptional 直したり、↑の Range のやつ直したり。
Avatar
その差分は勉強になりそうだな
Avatar
assoctypeに自身を指定できる奴(SubSequenceのアレ)は流石に入るかな? masterには入ってるから、4.1には入りますね。
1:14 AM
October 18, 2017 (initial branching): The swift-4.1-branch will be initially cut from master. なので。
Avatar
大きな機能はその initially cut from master 以降はマージされない方針ってことですか?
Avatar
  • October 18, 2017 (initial branching): The swift-4.1-branch will be initially cut from master.
  • Approximately every two weeks, master will be merged into swift-4.1-branch until the final branch date.
  • November 27, 2017 (final branching): The swift-4.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).
(edited)
1:20 AM
final branch dateまでにmasterへマージされれば入るかと(revertされなければ)
Avatar
Approximately every two weeks, master will be merged into swift-4.1-branch until the final branch date.
なるほど。
Avatar
Conditional Conformancesは流石に無理じゃないかな。
😭 1
Avatar
リカーシブなんとか、そう。それだけでも入るなら御の字かな
1:28 AM
そこら中に生えてたwhere句を駆逐できるから
Avatar
Swift 5 で async/await と Conditional Conformance が入ったらめちゃくちゃ快適な言語になりそう。
Avatar
まだHigherKindedType無いし変性はメチャクチャですよ
Avatar
RustのGeneric Traitはうらやましい
1:33 AM
HigherKindedTypeも欲しいンゴね
Avatar
SequenceとLazySequenceも根っこから分離したい、これはプロポーザル書くか
Avatar
HigherKindedType は諦めてます。
1:33 AM
変性は正直あんま必要にならないんですよねぇ。
1:34 AM
そもそも値型の範囲だとサブタイピングがないし。
Avatar
依存型とOwnership関係と外部モジュールspecializeが早く欲しい
Avatar
怪しげな変性が無くなればそれはそれで良いんですよ、今は中途半端だ
Avatar
型理論系はRustに足りて無くて、動作速度系はC++に足りてない。
1:35 AM
怪しげな変性問題ね・・・
Avatar
Ownership と言えばちょっと思ったんですが、 Ownership あったら ARC じゃなくても GC でいいとかないですかね?
Avatar
どういうこと?
1:36 AM
Ownershipを入れるのとGCを入れるのは真っ向から真逆のアプローチだと思う。
Avatar
GC ダメって言ってたのって、システム言語の領域を目指すには GC のパフォーマンスは許容できないとかいう理由だったと思うけど
1:37 AM
本当にパフォーマンス必要なとこは Ownership で解決して
Avatar
Ownershipの有無に関わらずGCあると世界は停止しそうですが
Avatar
アプリレイヤーとかは GC とかできないかな?
Avatar
D言語はGCの有無をスイッチできるようにしたけどライブラリの世界が2つに分断してつらそうってラトナーが言ってた
Avatar
最近だと循環参照嵌まりがちなのは専らクロージャ周りなんで値のキャプチャ周りが賢く出来れば良さそうと言うのがあって (edited)
1:41 AM
極端な話 [* foo]みたいにして明示的にキャプチャしないとコンパイルエラー、みたいな感じにすれば大分マシになる仮説を持ってるんだけどどうですかね
Avatar
あとシステム領域でもオブジェクトの共有パターンは出て来ると思うのでARCが無いとつらそう
Avatar
  • = (strong, weak, unowned)
Avatar
指定しなければstrongなのがだめってこと?
Avatar
そう
Avatar
変わるかなあ
1:42 AM
あるとしたら、 self が何もしなくてもキャプチャされることとかが問題だと思ってる
Avatar
無指定でキャプチャ出来るのが見えにくくなってる元だと考えている
Avatar
ローカル変数とか。
1:43 AM
strong性のほうじゃなくて、名前自動キャプチャのほうが問題
Avatar
それはローカル変数キャプチャするとselfつけろって言われない?
Avatar
self. つけなさいは言われるね。
Avatar
あークロージャの代わりにメソッド渡したときの挙動も、そうか
Avatar
GCじゃなくてもARCにしても、Memory Ownershipの世界ではリファレンスカウントの操作すらパフォーマンス的に許容できないのでは?
1:47 AM
なので世界を住み分けることになるのかなと思ってるんですが。
Avatar
えーっと、それはそうだけど、できるだけ排除する話と
1:47 AM
デザインパターンとしてARCが無理になる負担を強いる話しは別だと思う。
Avatar
GCじゃなくてもARC+サイクルコレクターとかでもいいけど、住み分けたアプリ側の世界では循環参照気にしなくていいようにできないかな?
Avatar
あと
1:48 AM
C++の参照の場合は一級参照だから、実体はどっかにあって、他のところからは参照/ポインタで共有し続ける事できるけど
1:49 AM
SwiftのOwnershipで入る参照は生き続けられないから
1:49 AM
その話の方向でいくなら一級参照がはいる方向に強化する必要がでてくる
1:50 AM
ようするに stored propertyの型を参照にはできない
1:51 AM
循環参照気にしなくていいようにできないかな?
これもできないと思ってて、 循環が解決できるトレーサーが、入れないところがあると、そこからリークしちゃう
1:52 AM
メモリ参照グラフにおいて、あるオブジェクトはGC対象ではない、とされているとき、 GC対象オブジェクト→GC外オブジェクト→GC対象オブジェクト って参照がつながってるときに、最後のやつがどうしてもマークスイープできない
1:52 AM
途中のGC外のオブジェクトから先をトレーサが見れないから。
Avatar
ん?リークじゃなく逆にまだ使いたいのに破棄されちゃうわけではなく? (edited)
Avatar
えーっと、それは設計で両方ありえて
1:54 AM
GC外からretain(というかルート参照登録)させる方法が無いとするなら、
1:55 AM
ユーザサイドで別の配列とかにいれて持っておいてねってことになるけど
1:55 AM
今度はそれの解放をユーザサイドでやるのがキツくて
1:55 AM
コールバッククロージャーとかですら大変面倒なことになりますよ
Avatar
GC/ARCの世界からそうじゃない世界に入る場合には明示的に何らかの方法でretainさせるしかないような気が。
1:55 AM
今でもそうなんじゃないかな? UnsafePointer の世界を挟むときとか。
Avatar
例えばJavaやJSだと
1:56 AM
C++のコードから、VMに対して、VM内オブジェクトを作らせてから
1:56 AM
それをルート参照に追加するAPIがある
1:57 AM
だから、Managed側から受け取ったオブジェクトを、Native側で、そのAPIで登録しておけば
1:57 AM
Native側からmallocしたようなイメージですね 対応するルート解除をしない限りSweepされなくなる
1:58 AM
今というかちょっと前のObjectiveC なら、 ARCがないMRCのモジュールの中から明示的にretainメソッドを呼ぶのに近いかも
Avatar
Ownership の世界って基本閉じてて本当にパフォーマンスが重要な部分にしか使われないイメージなんだけど、境界だけ気にしていればいいからそんなに複雑なことにならなくないかな?
Avatar
2つの構造体が、1つの構造体をポインタ経由で共有する、というデータ構造が作れないとつらくないですか?
Avatar
どういうこと?
Avatar
例えば class Cat { var toy: Toy? } と class Dog { var toy: Toy? } が class Toy {} を共有してるっていうのが今のARCだとできますよね
2:06 AM
Ownership で導入されるのは、 shared 参照とmoveonly structですけど、 ARCが無いってことは、classが無いので、↑みたいな構造が作れないです struct Cat { var toy: Toy? } struct Dog { var toy: Toy? } struct Toy {} とやってしまうと、これは共有じゃなくて、Toyの実体が2つになるので、データ構造としては意味が違う。
2:07 AM
struct Cat { shared var toy: Toy? } ←こういうことはできない、一級参照じゃないから
2:08 AM
struct Cat { var toy: UnsafePointer<Toy>? } ←こういうことならできますけど、これはUnsafePointerのじてんでOwnership Systemの保護から外れるので、C言語に戻ってるだけで、安全性が0
2:11 AM
SwiftのOwnership Systemは、↑のような、「共有したい状況」では何ら状況を改善するものではなくて、
2:11 AM
オブジェクトの所有者が明確な、「専有所有する状況」(とそれの貸出と移動)においてはいろいろ改善できるってだけなので、
2:12 AM
既存のclass ARC はまず前提にあって、その中で共有が要らない部分で一部の処理を最適化するためにあるって位置づけ
Avatar
なるほど。 Rust だとどうなってるの? first class な参照があるってこと?
Avatar
Rustの参照はfirst classなんですけど、関数の呼び出しをまたいで追跡したりする場合、ジェネリクスの型パラメータとして、寿命範囲を静的に追跡させるので、ファントムタイプみたいなイメージで
2:24 AM
↑みたいな例で動的な場面では多分参照では解決できないと思う
2:24 AM
Rustにも Rc<T> と Arc<T> があるので
2:25 AM
↑の例はそれらの参照カウンタコンテナ(スマートポインタ)を使うことになると思います
Avatar
なるほど。 Swift の classArc<struct> を強制したようなものか。
Avatar
そうです。 structにしてUnsafePointerだけで取り回せば、C言語に戻れます。
Avatar
ARCならミクロに実現できるけど、GCやサイクルコレクターだとマクロに参照グラフをたどれないといけないからOwnershipの世界を挟むときついのか。 (edited)
Avatar
Ownershipの世界にARCが全く無いってことになるとそこを挟むところが厳しいですね
2:31 AM
あくまでベースとしてARCは普遍的に使われていて、その繋がったグラフの端っこだけOwnershipで済ませる みたいな感じ。
Avatar
この前の Erasure のパターンの知識、結構応用が効く
3:47 AM
型パラメータをサブクラスで持って、親クラスではもたないと、型パラメータ部分を消せる
3:48 AM
その2者関係をBoxと名付けて外側の型を作ると、メソッド呼び出し時点のメソッドの型パラメータをボックスに焼きこんで保持するみたいな感じになる
Avatar
型パラメータをサブクラスで持って、親クラスではもたないと、型パラメータ部分を消せる
ちょうどKeyPathのクラス階層がそんな感じな気がする。ルートがAnyKeyPathで、そこからPartialKeyPath<Root>, KeyPath<Root, Value>みたいな。
Avatar
Observableの実装もそうなのかなぁ
2:08 PM
Mapとか
Avatar
SinkがBox相応の働きしてるならそうなんだろうけどあれは実装が別々だから違うな
Avatar
[Poll] A Swift quiz: let a: [Float] = [1, .nan] let b: [Float] = [1, .nan] let copy = a a == b // (1) a == copy // (2) What’s (1) and (2)?
Avatar
やばそう
Avatar
let e: Float = .nan let f: Float = .nan e == f // false
Avatar
.nanがcomputed valueで生成結果が毎回違う、かな
Avatar
ああaとcopyがおなじなのがおかしいんですか
Avatar
ナンとナンは==取るとfalseになるもの
Avatar
そういうものなのか
Avatar
はい
Avatar
同じインスタンスだったらequalというのが間違ってる。
Avatar
本当だ
Avatar
それを使ってナン判定ができます
Avatar
Float.nan == Float.nan // false let a = Float.nan let b = a a == b // false
Avatar
これ。 // Test referential equality. if lhsCount == 0 || lhs._buffer.identity == rhs._buffer.identity { return true } https://github.com/apple/swift/blob/master/stdlib/public/core/Arrays.swift.gyb#L2195-L2196
swift - The Swift Programming Language
Avatar
これどう修正するんだろ
1:06 AM
ここのif文取っ払えば治るのは治るけどパフォーマンスに影響出そう
Avatar
==(lhs: Array<Float>, rhs: Array<Float>) をオーバーロードとか?
Avatar
Double.nan
Avatar
自分自身と等しくないのが無限に湧きますよねぇ
Avatar
そもEquatable定義して必ずfalse返すカスタムオブジェクトが破滅するから
1:09 AM
これは取っ払うしかないな
1:12 AM
let a: [String: Float] = ["a": .nan] let a2 = a a2 == a こっちもだめ、Optionalは正しかった。
1:12 AM
Setもダメだな
1:13 AM
ボロボロだ
Avatar
ああ、falseになると思いきや、
Avatar
Buffer持ってる構造全滅滅滅じゃない
Avatar
アレイの実装によってtrueになっちゃうのか
1:13 AM
スイフトクイズ的だ
Avatar
Buffer持ってる=CoWが効く構造は
Avatar
それってどっちかというとFloatがNaNに関して同値性の伝播則を持たないことによるから
1:14 AM
Floatが壊れてるのでノーカンでよいよ
Avatar
定義されたEquatableの挙動を、CoWの実装の有無によって踏襲する/しないが生まれるのは微妙じゃない?
Avatar
例えばHashableは
1:16 AM
Equalならhashが同じじゃないといけない
1:16 AM
って規約を持つわけで
1:16 AM
Equatableの特性を厳密化すれば
1:17 AM
Arrayの責任ではなくなる。
1:18 AM
NaNは < も > も falseを返すので、ソート結果が安定しないのと同じ。
Avatar
twitterでも「Float, DoubleEquatableのルールを破ってるのが悪い」という話になってる。
👍 1
Avatar
ふむ
Avatar
ヤバ。両方 false にならないといけないのに、バッファが同じだったときに省略するコードが走ってんのかな?
1:53 AM
あれ?
1:53 AM
続きがロードされてなくて周回遅れのコメントをしてしまった
Avatar
時空が歪んだ
😵 1
Avatar
それってどっちかというとFloatがNaNに関して同値性の伝播則を持たないことによるから Floatが壊れてるのでノーカンでよいよ
これも同じ主旨のこと書こうとしてたw
1:57 AM
IEEE 754のNaN関連どうにかしてほしい
Avatar
まあでもFloatはどんな言語でもIEEE754準拠になっていてマシ
1:58 AM
負の整数のあまりつき除算とか、言語によって微妙に振る舞いが違ったりしてしんどい
Avatar
Java のラッパークラスの NaN 比較は壊れてる。 public class NaN { public static void main(String[] args) { Double a = Double.NaN; System.out.println(a.equals(a)); // true } }
Avatar
やば
2:01 AM
doubleとDoubleで結果が違うってこと?
Avatar
久しぶりに Java 書いたけど、指が自然に public static void main(String[[ args) と動くからすごい。
2:02 AM
うん < double と Double
Avatar
↑そういいながら [[ に typoしてますね
Avatar
Array.== tests for referential equality and returns true if the underlying buffer is shared between two instances. This provides for unexpected behavior in the case of comparisons involving floatin...
2:03 AM
この件についてのプルリクが立ってるんだけど。
Avatar
ヤバイことに気づいた。
2:04 AM
var dict = [Double: String]() dict[.nan] = "a" dict[.nan] = "b" print(dict) // [.nan: "a", .nan: "b"]
2:05 AM
これを防ぐために Java の Double は↑のような仕様になってた気がする。 (edited)
Avatar
if lhsCount != rhs.count { return false } + if lhsCount == 0 { + return true + } // Test referential equality. - if lhsCount == 0 || lhs._buffer.identity == rhs._buffer.identity { + if lhs._buffer.identity == rhs._buffer.identity + && !Element._containsExceptionalValues { return true }
2:06 AM
これAnyの配列とかAnyObjectの配列の場合に中身にfloatがあるケースとかで全部このコンサバなフローになっちゃうと思うんやけど・・・
2:08 AM
Anyとかの場合は == が使えないのか。
2:08 AM
@koher それ、値が取り出せないってことですかね?
2:11 AM
var d = [Float: String]() d[Float.nan] = "aaa" print(d[Float.nan]) // nil
2:11 AM
取り出せないですね
2:11 AM
ウケる。
Avatar
うん。取り出せない。
2:11 AM
無限に突っ込める。
Avatar
Float.nan.hashValueは同じだから
2:12 AM
毎回衝突してるなw
2:12 AM
草w
Avatar
DoubleFloatHashable やめた方がいいのでは?
Avatar
NaN以外ではうまく動くしちょっとぐらい壊れてもいいよ
Avatar
↓の最後もちょっと納得いかないんだよなぁ。 14> let nan = Double.nan nan: Double = NaN 15> nan < nan $R8: Bool = false 16> nan > nan $R9: Bool = false 17> nan == nan $R10: Bool = false 18> nan != nan $R11: Bool = true
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> {}
2:18 AM
@koher <> が反射しないのに ==!= は反射するのよくわからないですよね
Avatar
NaNをFloatingPointから外したほうが
2:19 AM
struct NaN
Avatar
外すと 0/0 で困る
Avatar
Python の↓どうなってんだ? $ python Python 3.6.1 (default, Apr 19 2017, 14:30:24) >>> from math import nan >>> d = dict() >>> d[nan] = "a" >>> d[nan] = "b" >>> d {nan: 'b'} >>> nan == nan False
2:20 AM
まさか Dict に突っ込まれる度に nan チェックしてんのかな?
Avatar
idenitty equalをまず見てるんじゃないですか?
Avatar
ボクシングされるってこと?値じゃないの?
Avatar
そもそもオブジェクトかも
Avatar
Floatの除算をthrowsにすればstruct NaN: Errorでいけるのでは
Avatar
除算をthrowsにしちゃったら
2:22 AM
めちゃくちゃおそくなっちゃうよ
Avatar
ふむー
Avatar
floatの利用シーンがおそおそになる
2:22 AM
やるとしてIntのoverflowケースみたいにクラッシュさせて
2:22 AM
NaNが産まれる除算は &/ にするとか?
Avatar
Int(0)/Int(0)はクラッシュやね (edited)
Avatar
うむ。
Avatar
NaNを許容する除算と許容しない除算を分けてNaNをError型にして許容しない方はクラッシュ、かなぁ
Avatar
あと C Interop も考える必要あるね
2:24 AM
/// The C 'float' type. public typealias CFloat = Float /// The C 'double' type. public typealias CDouble = Double
2:24 AM
いまはこう。
Avatar
うげうげのうげ
Avatar
float周りは高速計算領域の話題だから、まともなFloatを用意するなら完全に別の型体系にしたほうがいいんじゃないかな〜
Avatar
struct CFloat { init(_ source: Float) init(_ source: NaN) }
2:25 AM
こうなっちゃいますね
Avatar
いまのFloatをまともなやつにして速いコードはCFloatでやってね、もありか。
Avatar
昔デデキント切断による実数型を作れないか考えたことある。
Avatar
それはそれでありだと思う
Avatar
struct FiniteFloat とか
2:26 AM
+infと-infはあってもいいんだろうか・・・
Avatar
今のFloatをCFloatにしてNaNを含まないFloatを新設、とかありえそう
Avatar
実数型を作る話だ
Avatar
Float.infinity こいつもいるのか
Avatar
うん。
2:27 AM
あともっというと +0-0 がある。
Avatar
実数型作るなら inf はいらないのでは。
Avatar
Float.infinity == (Float.infinity * 2) // true おお~~~~
2:27 AM
ホンモノぽいw
Avatar
単純な実数型の外に
Avatar
クソみたいな小細工がいろいろ仕込まれててウケるよ、Floatの変なやつら
Avatar
無限も扱える体系を作るのがよさそう
2:29 AM
あとその前に有理数を分離しなきゃ。
Avatar
print(Float(1) / Float.infinity) // 0.0 print(Float(-1) / Float.infinity) // -0.0
2:30 AM
https://ja.wikipedia.org/wiki/超実数 超実数の全体 *R は実数体 R の拡大体であり、 1 + 1 + ⋯ + 1 1+1+\cdots +1 の形に書ける如何なる数よりも大きい元を含む。
Avatar
なんかこういうのを形式的に実装するのかな
Avatar
https://www49.atwiki.jp/aniwotawiki/pages/11249.html …ここからが本題の超実数の話。先程、我々は実数体Rに∞と-∞を追加した集合である拡大実数を得た。 注意深い読者なら気付いただろうが、この集合は拡大実数「体」ではない。つまり、これは体ではない。 我々はまず自然数全体の集合Nから始め、Nが元々持っていた構造(足し算や掛け算、大小関係)を壊さないように慎重に拡張してきたのだが、 Rに∞と-∞を追加したことでその構造が壊れてしまったのである。 拡大実数を構成する際、 「限りなく大きくなる」代数的数の列は「∞に限りなく近づく」代数的数の列 だという拡大解釈を行ったが、 これが失敗だった 。 「限りなく大きくなる」代数的数の列として挙げた{1,2,3,4,…}と{2,4,6,8…}は確かに両方とも「限りなく大きくなる」代数的数の列であることは間違いない。 しかし{1,2,3,4…}という列に比べ{2,4,6,8…}という列は2倍の勢いで大きくなっていく。 この事実を無視し、単純に両方を∞という同じ数に近づく列だと考えてしまったのが原因でおかしなことになってしまったのである。 この問題を解消するには、「異なる勢いで大きくなる列」には「異なる∞」を対応させればよい。 この方法を用いれば、Rの体構造を保ったまま∞と-∞を追加することができる。これを超実数「体」と呼ぶ。
登録日 :2010/09/05(日) 15:45:19 更新日 : 2017/09/30 Sat 14:10:34 所要時間 :約 4 分で読めます ▽タグ一覧 ためになる項目 ためになる項目←理解...
2:35 AM
taketo1024 さんに作ってもらおうw
Avatar
Swift.Floatが壊れてるのはしかたないのでまともなFloatを作ってそれを使うというスタンス
Avatar
$ kotlinc Welcome to Kotlin version 1.1.2-2 (JRE 1.8.0_131-b11) Type :help for help, :quit for quit >>> val nan = Double.NaN >>> nan == nan false >>> nan === nan false >>> val map = mutableMapOf<Double, String>() >>> map[nan] = "a" >>> map[nan] = "b" >>> println(map) {NaN=b}
Avatar
===がfalseなのが謎だな
Avatar
お、おもしろいの発見した
2:46 AM
>>> fun <T> eq(a: T, b: T): Boolean { return a == b } >>> nan == nan false >>> eq(nan, nan) true
Avatar
あ、unboxされてるのか
2:46 AM
その場合は Genericなコードになるから == が <T> のboxのidentityになってるんですね
Avatar
Kotlin には普段見えないラッパーが見える
Avatar
=== の場合はstaticなDoubleのコードだからunboxされて == と同じ処理になると
Avatar
identity じゃなくて同値性だけど、 Doubleequals は前述の Java の通りだから。
Avatar
あー JAvaのDoubleのequalsも踏まえないといけないのかw
Avatar
返り値が Optional版 や throws 版を作る時、suffixやprefixで表現する時、どうしてます? 最近はこんな感じにやってるんだけど↓ // prefix func mayGetCat() -> Optional<Cat> func mustGetCat() throws -> Cat // suffix func getCatOrNone() -> Optional<Cat> func getCatOrThrow() throws -> Cat
Avatar
throwsだけ作って利用者側がtry?すればいいじゃんと思ってるけど
Avatar
それだとパフォーマンス上不利だから 利用者が try? するぐらいなら Optional版 も用意したい
Avatar
なるほど
3:12 AM
オーバーロードするとしんどいんだっけ
Avatar
例えば複数行クロージャの中で使うと推論が効かないのでちょっと不便な場合が出てくる (edited)
3:13 AM
名前でわけておくとreturnのところでオーバーロード曖昧性がないのでそこから型が確定できる
3:15 AM
まあ明示すれば解決するから、同じ名前でオーバーロード流派もそれはそれでありだと思う
3:16 AM
↑の例で個人的に気になってるところは、 OrNone vs OrNil OrThrow vs OrError
Avatar
struct May { private init() {} static let may = May() } struct Throw { private init() {} static let `throw` = Throw() } func getCat(_ o: May = .may) -> Cat? { return Cat() } func getCat(_ o: Throw = .throw) throws -> Cat { return Cat() } 引数で明示できるようにしてみた
3:16 AM
getCat(.may)ならOptionalに確定
Avatar
おお〜 短い名前と、必要なときの明示を両立するのか おもしろい
3:17 AM
それだと英語が変になるから、 .orNone.orThrow のほうが好きかな getCat(.orNone)
Avatar
まあそれはどちらでも
3:17 AM
着想としては[1,2,3][...]ベースかな。
3:22 AM
tryと?が演算子扱いならgetCat(?)とgetCat(try)が使えた気がする
3:22 AM
実際は違うのでムリ
Avatar
なるほど
Avatar
@omochimetaru メソッド名につけるならOrNilとOrThrowがすきかなあ
3:24 AM
OrErrorだとthrowされるのかクラッシュするのかなんか怖そう
3:24 AM
普段はオーバーロード+型明記派になってる
Avatar
たしかに OrThrowならどう考えてもthrowだよな
3:25 AM
OrNilじゃなくてOrNoneだと思うんだよね、 nil が .none になるのであって nil 自体は返ってきてない
3:25 AM
Swiftにnilなんていう値は存在しないのだ
3:26 AM
リテラルの型としては存在するけど実行時の型は .none などになる
Avatar
それで言うと取れる値としては.noneかErrorかどっちかという話なので
3:27 AM
orNone, orErrorがいいのでは
Avatar
Either < T , Error >だったら orError だと思うんだけど
3:27 AM
「値が返る」ことと「throwされる」ことを
Avatar
実態はthrows () -> Tだから、というはなしか
Avatar
別と捉えると、 OrThrowの方がより明確かな〜って
Avatar
OrNone, OrError, OrDie
Avatar
クラッシュ系はどれがいいのかな〜 > OrCrash OrNever OrDie
3:31 AM
perl だと or die イディオムありますよね。
Avatar
orDieは省略したくないなw
Avatar
orDie だけデフォルト引数設定しないとか?
Avatar
struct OrNone { private init() {} static let orNone = OrNone() } struct OrError { private init() {} static let orError = OrError() } struct OrDie { private init() {} static let orDie = OrDie() } func getCat(_ o: OrNone = .orNone) -> Cat? { return nil } func getCat(_ o: OrError = .orError) throws -> Cat { throw Cat.Error.fail } func getCat(_ o: OrDie) -> Cat { fatalError() }
3:34 AM
ということで
3:35 AM
3:35 AM
補完バッチリ効いてるのいいすね
Avatar
オシャレだな・・・
3:35 AM
推論効けば短く書けるし明示するときは指定できるのか・・・
Avatar
推論効くときは効かせるスタイルもっとはやってほしい
3:36 AM
左辺vs右辺とか不毛だし両立できるよっていう認識広まるとうれしいですね
Avatar
ABI work to remove unnecessary _Strideable protocol and use Strideable everywhere instead, which already conforms to Comparable. Initial changes are done by @airspeedswift.
2:52 AM
あの怪しい _Strideable が消えそう
Avatar
protocol Animal {} protocol Cat: Animal {} class Dog: Animal {} Dog.self is Animal.Type // true Cat.self is Animal.Type // swift 3.2 true, swift 4.0 false
10:48 AM
これって話題になりましたっけ
Avatar
Swift4で違うの!
10:48 AM
俺は初耳
10:49 AM
っていうかfalseなのか・・・
Avatar
あれこれ出来たはずなのに死んだわおっかしいなと思ったら
😇 2
Avatar
こういうことやりたいんですが、なんかいい感じのオペレータとかあるんでしょうか? intStream .map(ensuredPositiveIntString) .catchErrorJustReturn("マイナスだよ") .subscribe... // 👈 エラー来てもnext扱いで死なないでほしい enum Error: Swift.Error { case isNegative } func ensuredPositiveIntString(i: Int) throws -> String { if i < 0 { throw Error.isNegative } return String(i) } ensuredPositiveIntStringResult<String, Error> を返すより、単純な throws にしたいんですが
Avatar
flatMapの中でやる
Avatar
こういうことです? intStream .flatMap { do { return try Observable.just(ensuredPositiveIntString(i: $0)) } catch { return Observable.just("マイナスだよ") } }
Avatar
ensuredPsitiveを、IntかErrorが出るObservableにすると解りやすいかも
Avatar
intStream .flatMap(ensuredPositiveIntString(i:)) .subscribe... // 👈 エラー来ても死なない func ensuredPositiveIntString(i: Int) -> Observable<Int> { if i < 0 { return Observable.error(Error.isNegative) } return Observable.just(String(i)) } (edited)
Avatar
intStream.flatMap{ ensurePositive($0) .catchError { エラー処理 } } .subscribe(メイン処理)
8:34 AM
こうです
Avatar
なるほど
8:36 AM
うーん、できればensuredPositiveIntStringはRx関係ないpure swiftな世界にしたいのだけれど、それは既存の仕組みでは難しいですか
Avatar
throws Tをラップするオペレーターがあれば楽かなぁ
8:38 AM
結構オレオレで作るんですよね
8:39 AM
Observable.from(throws: @escaping () throws -> T)
Avatar
死なないという条件的には微妙ですがretry使えるならそれでもいいのでは
Avatar
こんなかんじかな extension ObservableType { static func from<U>(_ f: @escaping (Self.E) throws -> U) -> ((Self.E) -> Observable<U>) { return { (e: E) in do { let u = try f(e) return Observable.just(u) } catch(let e) { return Observable.error(e) } } } }
8:41 AM
お、retry実は使ったことないので探ってみます
8:45 AM
ここまであったほうがいいか extension ObservableType { static func from<U>(_ f: @escaping (Self.E) throws -> U, catch: (Error) -> U) -> ((Self.E) -> Observable<U>) { return { (e: E) in do { let u = try f(e) return Observable.just(u) } catch(let e) { return Observable.just(catch(e)) } } } }
Avatar
んーなんか違う
8:46 AM
引数無しで返り値はEです
8:47 AM
throws () -> TをObservable<T>にしたいので
Avatar
イメージ涌ききれてないけど多分そっちのほうが正解だと思うので、動くもの使って弄ってみますー
Avatar
@t.ae 失敗したり成功したりする処理ならretryは有効だけど、何度やっても失敗する場合はretryは使えないのでは、と思いました
Avatar
あーソースがPublishSubjectのときに使ってるパターンなのでそれだけ考えてました……
Avatar
throwsで殺さないやつ、自分が考えるとこういうやりかたに行き着くんですが、 @tarunon 的にはどういうのイメージしてたんでしょう
Avatar
単純に、エラーが流れるとdisposeなんで、flatMapの中でsubscribeを毎回作れば都度disposeされても問題ないという話です。
11:13 AM
stream.map(someThrowableFunc).catchError().subscribe() // これだとエラーが流れた時点でおしまい stream.flatMap { Observable.from(someThrowableFunc($0)).catchError() // Errorでdisposeになるのはこのsubscription }.subscribe() // 従ってこちらには影響しない
11:13 AM
これはcompleteが流れる場合も同じように (edited)
11:14 AM
で、retryはErrorが流れてきた場合はsubscribeしなおす、というものなので、源流でreplayがついてる場合はErrorを無限に繰り返すことになる
Avatar
なるほど Observable.from(throws: @escaping () throws -> T) の使いどころがよくわかってなかったんですが把握 こういうことですね
Avatar
それだけなら何もしなくても、これでも長くないし別に困らない感 Observable.from([1, 2, 3, -1, 4, 5]) .flatMapFirst { Observable.just($0) .map(ensuredPositiveString) .catchError { _ in .just("つづく") } } .subscribe(onNext: { print($0) }) (edited)
Avatar
昨日の #swtws での @omochimetaru さんの発表を見て、 SwiftyAlgebra の行列計算が遅すぎて悩んでいることについて何かヒントを頂けたらと思い、質問させていただきます。 https://github.com/taketo1024/SwiftyAlgebra/blob/master/Sources/Matrix/Matrix.swift 元々は行列の積を public static func * <p>(a: Matrix<R, n, m>, b: Matrix<R, m, p>) -> Matrix<R, n, p> { return Matrix<R, n, p>(rows: a.rows, cols: b.cols) { (i, k) -> R in // 積の (i, k) 成分を返す. // a の i 行と b の k 列の積和を計算. return (0 ..< a.cols) .map({j in a[i, j] * b[j, k]}) .reduce(0) {$0 + $1} } } のように書いていたのですが、これがサイズ 200x200 ぐらいでも 7 秒近くかかってしまい、これを次のように書き換えたところ 7秒 → 0.2 秒に改善されました。 public static func * <p>(a: Matrix<R, n, m>, b: Matrix<R, m, p>) -> Matrix<R, n, p> { // 行列の1次元グリッドを生成して Matrix を作る var grid = Array(repeating: R.zero, count: a.rows * b.cols) var p = UnsafeMutablePointer(&grid) for c in 0 ..< a.rows * b.cols { let (i, j) = (c / b.cols, c % b.cols) var (q, r) = (UnsafePointer(a.grid), UnsafePointer(b.grid)) q += a.gridIndex(i, 0) r += b.gridIndex(0, j) var x = R.zero for _ in 0 ..< a.cols { x = x + q.pointee * r.pointee q += 1 r += b.cols } p.pointee = x p += 1 } return Matrix<R, n, p>(rows: a.rows, cols: b.cols, grid: grid) } できればこういうポインタ丸出しのコードは書きたくないので(そっち方向でやるなら言語を変えた方が良さそうという気持ち)、なんとか上のような書き方のまま改善したいと思っているのですが、上の書き方がこんなにも遅い理由は思い当たるものありますか? init に渡す closure の中で行列 a, b にアクセスしてることから、丸ごとコピーされちゃったりしてるのかなと疑っています… 🤔 Thanks in advance 🙂 (edited)
Contribute to SwiftyAlgebra development by creating an account on GitHub.
🙂 1
Avatar
今ちゃんと読めてないですがspecializeの問題とかあるかも?また後で見てみます。
👌 1
Avatar
Submodules/Eigen のチェックアウトが全然終わらない
Avatar
あれれ、Submodule 外してたと思ったんですが 😨
Avatar
/.gitmodules にエントリがありますね
Avatar
ありゃりゃ、それは失敗しました、消しときます🙇
4:45 AM
そのままでも動くはずです。
Avatar
了解です
🙇 1
Avatar
まず、クロージャがaとbをコピーしてるというのは無さそうです。nonescapeなクロージャはスタック上の値をポインタ参照するので。 で、TimeProfilerで調べてみたら、Matrix.initに渡してるクロージャの中のmapとreduceが、CountableRangeに対するprotocol witness呼び出しをしていたんで、そこらへんがインライン化されてないっぽいです。 Matrix.multiply自体はSpecializeされているぽいけど、Matrix.initのクロージャの中身が最適化されてない (edited)
5:54 AM
試しに Matrix.initの中身だけ手動で書いたら、 swifty(1): 9.03 pointer(2): 0.18 に対して、 forloop(3): 1.93
5:54 AM
public static func multiply3<p>(a: Matrix<R, n, m>, b: Matrix<R, m, p>) -> Matrix<R, n, p> { assert(a.cols == b.rows, "Mismatching matrix size.") return Matrix<R, n, p>(rows: a.rows, cols: b.cols, type: (a.type == b.type) ? a.type : .Default) { (i, k) -> R in var x = R.zero for j in 0..<a.cols { x = x + a[i, j] * b[j, k] } return x } }
5:55 AM
50倍ぐらい差があるところを10倍差ぐらいまで追いついた。
Avatar
18.37 s 96.2% 458.00 ms closure #1 in static Matrix.multiply3<A>(a:b:) 17.16 s 89.9% 1.09 s Array.subscript.getter 5.11 s 26.7% 696.00 ms _ArrayBuffer._checkInoutAndNativeTypeCheckedBounds(_:wasNativeTypeChecked:) 4.92 s 25.7% 725.00 ms swift_bridgeObjectRetain 3.62 s 18.9% 3.62 s _swift_release_ 819.00 ms 4.2% 737.00 ms Array._getElement(_:wasNativeTypeChecked:matchingSubscriptCheck:) 503.00 ms 2.6% 503.00 ms _swift_isClassOrObjCExistentialType 441.00 ms 2.3% 441.00 ms swift_bridgeObjectRelease 360.00 ms 1.8% 360.00 ms __swift_memcpy8_8 137.00 ms 0.7% 137.00 ms swift_release 95.00 ms 0.4% 0 s <Unknown Address> 43.00 ms 0.2% 0 s 0x7fff5d2ef24f 17.00 ms 0.0% 17.00 ms swift_retain 214.00 ms 1.1% 214.00 ms _swift_isClassOrObjCExistentialType
6:05 AM
次に支配的なのが subscript.getter で、これ、Matrix.subscript内部で grid に indexを与えて値を取り出すところなんですけど、 ここで型がspecializeされてなくて、Ring型のexistentialになっちゃってるせいで ただのDoubleを出し入れするだけなのにヒープ化されちゃってる。 swift_bridgeObjectRetainと_swift_release_のコスト。
6:07 AM
93%がArray.subscriptで、積和の計算は7%しか時間がかかってない
Avatar
@t.ae もこれよく困ってるよね ジェネリック<T>型が内部で持つ Array<T> が existential 化(boxing)されてクソ遅いやつ
Avatar
お!きた!
6:35 AM
ポインタ版より2倍はやくできたぞ
😍 1
😱 1
Avatar
ぬぉッ…!めっちゃやってくれてる😂
Avatar
@_inlineable つけるっていう裏技を使った・・・
Avatar
なんと…!!!
Avatar
とりあえずプロジェクト共有します
Avatar
感謝です…!!!
Avatar
https://github.com/omochi/SwiftyAlgebra/tree/inlineable ↑この inlineable ブランチで /Workspace/Sandbox/SwAlSandbox.xcworkspace に、Mac用コマンドラインアプリとしてビルドしていて
Contribute to SwiftyAlgebra development by creating an account on GitHub.
6:40 AM
@Taketo Sano のポインタ実装のmultiply2と、インライン化させたmultply4を100x100行列の掛け算1000回をやって秒数が出力される。
6:40 AM
問題はインライン化させるためには経由する関数呼び出しと参照するstored propertyが全部 public かつ inlineable で無ければならないので、
6:40 AM
grid とかが internal から public になってしまっているので実用性が無いということ・・・
6:43 AM
multply4はもともとのバージョンを forループに書き直したバージョン( initの中にもmapがあったんでこれも initを増やした
Avatar
@_inlineableはズルだわw
Avatar
まあずるなんだけど、遅い原因が existential にあるってことがわかった。
Avatar
ジェネリック<T>型が内部で持つ Array<T> が existential 化(boxing)されてクソ遅いやつ 👆これはどういうことなんです?
Avatar
はやく公式な機能になって欲しいね
Avatar
えーっと、 Array自体は Double を直列にメモリで持ってるんですけど
6:46 AM
Matrix.subscript は、 R としてコンパイルされた実装しかもってないから
6:47 AM
subscriptを呼び出すときに、gridへのアクセスが、ナマの [Double] じゃなくて [R] 扱いで、
6:47 AM
DoubleからRにラップして取り出して、
6:47 AM
取り出してきた側でまたDoubleに戻す、となっちゃってて
6:47 AM
そこでヒープ上にboxしたりunboxしたりしてクソ重い
Avatar
なんぞ😂
6:48 AM
インライン化の正式機能化がちょうど議論中だから
6:49 AM
待ってれば言語が改良されて解決するかも・・・
6:49 AM
ただ、現状のディスカッションだと、 internal な stored property が絡んでるとやっぱりインライン化されないので
6:49 AM
このままだと微妙ですねえ
Avatar
なるほどです…! Double というのは R=Double とした場合ってことですよね(Int なら Int 型で、subscript で無駄に box/unbox されるという理解であってます?)
Avatar
あ、もちろん、そうです。
👍 1
6:50 AM
なので、これを、回避する裏技として
6:52 AM
Image<T, P> に対して、実装をwhere付きのextensionのオーバーロードを用意したり・・・
6:53 AM
EasyImagy - Makes it easy to deal with images in Swift
6:53 AM
でも、 @Taketo Sano のMatrixは 要素の型だけじゃなくて、 ColNum と RowNum も型パラメータに入ってるから、
6:53 AM
特定の型について事前に用意しておくこの方針は無理そうだなあ
Avatar
なるほど…😫これは絶対に質問しないと分からなかった…😵
6:54 AM
コードも後で見てみます!(いま新幹線なので🚄
Avatar
スペシャライズに期待しないで型パラメータが特定の型のときの実装を明示的に書いておくと、特定の型のときは必然的にスペシャライズされた実装が使われる裏技だけど、 事前に用意した型にしか効かないし、型パラメータが多いとその組み合わせになって現実的に無理ってことですね
Avatar
@koher さんの言ってた specialize の問題ってこれだったんですね😂
Avatar
ですね
Avatar
要素アクセス以外の関数は一回の処理で何万回も呼ばれるようなことはないはずなので、ひとまずはそこだけインライン化できれば僕のケースでは問題なさそうです!
7:01 AM
これで掃き出しも相当早くなりそう😃
Avatar
なんか微妙だったのが、var grid のwillSetで
7:02 AM
clearCacheが呼ばれていて、smithNormalFormCacheを参照していたので
7:02 AM
この2つもpublicにする必要がありました。
Avatar
willSet もまた重い原因っぽかったんで、消そうと思ってます(clearCache はユーザ(僕しかいないが)の責任で呼ぶ方向で)
Avatar
なるほど。
Avatar
あ、そうか、privateなものが絡んでもinline化したい話についても、話題は進んでた。使用提案としては別文書になる予定みたいだけど
7:12 AM
そのうち何もかもいけそうやな
Avatar
(0 ..< n).reduce みたいなことも generic 型が絡む場合やらない方がいいんですか?かなりこのパターン多用してます。
Avatar
そのパターンでもちゃんとインライン化できるから大丈夫だと思います ただ、どういうときにインライン化されてどういうときにされないのか、僕も完全にはわかってないので、いったん検証のためにforループにしました
Avatar
何もかも publicにしなくても、 @_versioned をつけておくと internal に保っておけるので少し改良しました
Avatar
おぉw 知らないアノテーションがたくさんw
Avatar
これ系は正式仕様じゃないのでSwiftのアップデートでいきなりぶっ壊れたりコンパイラのバグを引き出したりする可能性があるので注意です。 (edited)
7:31 AM
ただ、標準ライブラリの内部では多用されています。
7:32 AM
元のバージョンと forloopのバージョンだと差が出るのでもうちょっと調べ中・・・
😍 1
Avatar
うーん、最適化が絡んでシンボルが消えちゃうので何が起きてるのかはっきりとはわからないんですが、 genericsは関係なく、普通に range.map.reduce が重い感じがしますね
7:42 AM
クロージャの呼び出しのたびに、 mapの返り値としてArrayが生成/破棄されているコストが重そう・・・
Avatar
なるほどなるほど
Avatar
Matrixのinitializerのほうは multiply1回につき1回なんで
7:43 AM
こっちは let grid = (0 ..< rows * cols).map { (index: Int) -> R in let (i, j) = index /% cols return g(i, j) }
7:43 AM
これで問題ないと思うんですけど
7:44 AM
行列要素ごとの↓が苦しい return (0 ..< a.cols) .map({j in a[i, j] * b[j, k]}) .reduce(0) {$0 + $1}
7:45 AM
10.12 s 96.2% 659.00 ms specialized closure #1 in static Matrix.multiply1<A>(a:b:) 3.70 s 35.1% 3.70 s _swift_release_ 2.27 s 21.6% 375.00 ms swift_bridgeObjectRetain 1.91 s 18.1% 0 s 0x7fff5dcb674f retainとreleaseで50%ぐらいかかってて、多分この正体が map の返り値。
Avatar
なんか色々解決されてた。
Avatar
なるほどなるほど。
Avatar
mapreducemutating 版を作ったらパフォーマンス改善しないかな?
Avatar
大量に呼ばれるケースでは Range map はやらない方がよさそうですね。
8:01 AM
自前でそういう Sequence を作るってことです?
Avatar
extension で生やすとかですね。思いつきですが、生成破棄の問題なら無駄な生成と破棄を減らせそう。
Avatar
なるほどなるほど
Avatar
@_inlineable public static func multiply3<p>(a: Matrix<R, n, m>, b: Matrix<R, m, p>) -> Matrix<R, n, p> { assert(a.cols == b.rows, "Mismatching matrix size.") return Matrix<R, n, p>(rows: a.rows, cols: b.cols, type: (a.type == b.type) ? a.type : .Default) { (i, k) -> R in var x = R.zero for j in 0..<a.cols { x = x + a[i, j] * b[j, k] } return x } } @_inlineable public static func multiply4<p>(a: Matrix<R, n, m>, b: Matrix<R, m, p>) -> Matrix<R, n, p> { assert(a.cols == b.rows, "Mismatching matrix size.") return Matrix<R, n, p>(rows: a.rows, cols: b.cols, type: (a.type == b.type) ? a.type : .Default) { (i, k) -> R in sigma(0 ..< a.cols){ j in a[i, j] * b[j, k] } } }
8:23 AM
@_inlineable public func sigma<I, T: AdditiveGroup>(_ range: CountableRange<I>, _ f: (I) -> T) -> T { var s: T = T.zero var i = range.startIndex while i != range.endIndex { s = s + f(i) i = range.index(after: i) } return s }
8:23 AM
これでも10倍ぐらい遅い
8:23 AM
Σを関数化すれば map, reduce がなくなって Array を使わないのでいけると思ったけど駄目だった (edited)
Avatar
お手上げだ
8:37 AM
これ以上は単純化してLLVMIR見比べてみないとわからん・・・
Avatar
すいません、ありがとうございます!
Avatar
教えて頂いた方法で自分の方でも対応してみました。 https://github.com/taketo1024/SwiftyAlgebra/commit/7543dfc0d0e667a7f2babe937419422c07452f58 subscript を @_inlineable にして、従来通り/命令型に書き換え/ポインタ版 で速度を比較して見ましたが、 original : 5.456 sec. imperative : 1.812 sec. pointer : 186.214 msec. となって、やはりポインタ版が圧倒的に速いようです。何かやりたりていないことがあるのかな…?
Avatar
チェックアウトしてそのまま(Debugビルド) original : 6.072 sec. imperative : 2.023 sec. pointer : 334.983 msec. Release Build に変更 original : 5.486 sec. imperative : 1.306 sec. pointer : 102.905 msec. (edited)
12:30 PM
mul2を @_inlineable, Release original : 5.773 sec. imperative : 54.375 msec. pointer : 113.603 msec. (edited)
12:31 PM
mul2とmul3を @_inlineable、Release original : 5.599 sec. imperative : 49.306 msec. pointer : 57.74 msec. (edited)
😮 1
12:33 PM
mul2とmul3を @_inlineable, Debug original : 6.505 sec. imperative : 2.068 sec. pointer : 201.69 msec. (edited)
12:37 PM
おそらく、そもそもsubscriptアクセスを行う関数(ここではmul2とmul3)自体がインライン化されないと、その先のsubscriptのインライン化もされないです。 subscriptだけinlineableであっても、mul2をコンパイルする時点ではジェネリックなRとして取り扱うコードしか生成しようがないからです。 利用時に Int を渡してmul2をインラインコンパイルするときに初めて、その先のsubscriptまで具象型Intが与えられたバージョンが生成されます。
12:41 PM
それと、Releaseビルドで、Optimizationオプションが -O で有効になっていないとだめで、Debugビルドではinlineableであってもインライン化はされないみたいですね。 (edited)
Avatar
なるほど!
12:48 PM
演算子の関数も inline 化できるのかな?(後でやってみます)
Avatar
できますよ。 func * に @_inlineable をつけた original : 3.683 sec. imperative : 47.842 msec. pointer : 55.317 msec. func * と、 sum に @_inlineable をつけた original : 786.015 msec. imperative : 51.296 msec. pointer : 53.369 msec.
12:54 PM
で、ここまでやって、まだ originalとimperativeに15倍の差が出ているのが、謎・・・
Avatar
うーむ…しかし元の7秒から実に10倍も早くなりましたね😍
Avatar
あー、 Matrix.init@_inlineable をつけたけど、かわらないですねえ original : 763.616 msec. imperative : 48.467 msec. pointer : 50.94 msec.
12:58 PM
そこでインライン化が止まっちゃって、Matrixの要素ごとにクロージャを呼び出す形は変わらなくって、遅いのかもしれないです。
Avatar
@inline(__always)@transparent なんてのもあるんですね。どういう違いがあるかご存知ですか?
Avatar
transparentは忘れちゃったけどドキュメントはここにあります https://github.com/apple/swift/blob/643d913ffce313238132e0e90ccb8bb2e93fc826/docs/TransparentAttr.rst @inline() は、とりあえず、 @inline(never) でインライン化絶対拒否は正規仕様で、 @inline(__always) は忘れました。 ここで、正規じゃないから文書は無いよって回答がある・・・ https://bugs.swift.org/browse/SR-182
swift - The Swift Programming Language
2:34 AM
@specialize だかなんだかそんなんもありますね
2:35 AM
似たようなのがいろいろあるので、それぞれちゃんと調べれば、もっと状況を改善できるかもしれないな。
Avatar
Matrixもそうですけど型じゃなくて型が持つ値のみを使う場合にいい感じの書き方無いですかねえ。 スペシャライズはどうも面倒……
Avatar
@omochimetaru こちら再現できました! original : 649.904 msec. imperative : 54.653 msec. pointer : 54.364 msec. かなり前進した感😃✨✨✨✨✨✨
Avatar
おお。
2:46 AM
@t.ae > スペシャライズはどうも面倒…… < これは手書きスペシャライズのこと?
Avatar
ちゃんと追えてないんですが、↓って map の中の計算を reduce の中に持って行ったら問題ないんじゃないでしょうか? return (0 ..< a.cols) .map({j in a[i, j] * b[j, k]}) .reduce(0) {$0 + $1}
2:49 AM
mutating func 化は的外れだった。そもそも map する時点で mutating じゃないし。 (edited)
Avatar
でもそうすると積和っぽくなくなりません?式を書き下す感じになってしまう
2:49 AM
書き方を工夫して早くするという観点では、 forループにすれば良いってことはわかっているので
2:50 AM
↑のswiftyな書き方のまま、同等の性能を出したいというのが残課題です
Avatar
reducdfor にするよりはわかりやすそうな気も?
Avatar
sigma はどうですか? (edited)
2:50 AM
和を取るって意味を関数名に退避することで + を書かなくて済むのでより明確になるし数式に近くなる
Avatar
@omochimetaru 手書きも@_specializeも網羅が面倒ですね。
Avatar
@t.ae ああ、アノテーションを付けて回るのが面倒ということか。
Avatar
@omochimetaru sigma の実装が for じゃなくて while なのはなぜ? (edited)
Avatar
@koher 最初 for でやったんだけど全く速度が変わらなかったから 書き換えてみたけどそれでもだめだった。
2:54 AM
@_specialize にもドキュメントがあった
Avatar
sigma の層があってもいいけど、 reduce で同じパフォーマンスが出るんだったら sigma の実装が reduce でもいいかも。
Avatar
return Matrix<R, n, p>(rows: a.rows, cols: b.cols, type: (a.type == b.type) ? a.type : .Default) { (i, k) in (0 ..< a.cols).sum { j in a[i, j] * b[j, k] } } 今こういう感じに書くようにしてみてて、 sum@_inlineable にすると、 original : 325.293 msec. imperative : 56.286 msec. pointer : 50.375 msec. これぐらいまで差が縮まりました。 この 250 msec の差は、200 x 200 回 closure を関数として呼び出してる分のオーバーヘッドなのかなとか想像してます🤔 (edited)
Avatar
@koher ああ、それはそうですね、前提として reduceの前のmapが悪いのかと思って。
Avatar
map で無駄な Array が生成されるのが問題なんだったらそこは回避できそう。 (edited)
Avatar
@koher あー言ってるのはreduceに全部書く方式か。それでもよいかと。 (edited)
2:56 AM
200 x 200 回 closure を関数として呼び出してる分のオーバーヘッド
そうなんですよね〜 そこが最後の壁、そこも init の中に展開してほしいんですけどね。
Avatar
sum の中で Array を生成せずに imperative な書き方してます。 public extension Sequence { @inline(__always) public func sum<G: AdditiveGroup>(mapping f: (Element) -> G) -> G { // MEMO reduce is slow. var res = G.zero for e in self { res = res + f(e) } return res } } (edited)
2:58 AM
ちなみに @inline(__always)@_inlineable の違いはなんだろうと思って調べてみたんですが、ここを見ると一個の関数に両方ついてるのがたくさんあって謎でしたw https://github.com/apple/swift/blob/master/stdlib/public/core/BridgeStorage.swift
swift - The Swift Programming Language
2:59 AM
@_inlineable // FIXME(sil-serialize-all) って書いてあるんで、いずれは消える予定?
Avatar
どっちかは自身のことでどっちかは自身の内部の話とか、かなあ? あとableってついてるし可能性を保証するやつと絶対やらせるやつなんでしょうねえ
Avatar
// MEMO reduce is slow.
これはなんでなんでしたっけ?スペシャライズされれば変わらなさそうな気も。
Avatar
それを書いた時点では reduce が遅いのが原因かと思ってそう書きました。
3:00 AM
今ちょっと書き直して調べてみます。
3:02 AM
public extension Sequence { @inline(__always) public func sum<G: AdditiveGroup>(mapping f: (Element) -> G) -> G { return self.reduce(G.zero){ $0 + f($1)} } } before: 325.293 msec. after: 293.025 msec. おぉ、なんか速くなりました💪w (edited)
Avatar
おお
Avatar
@inline(__always) public init(rows r: Int? = nil, cols c: Int? = nil, type: MatrixType = .Default, @inline(__always) generator g: (Int, Int) -> R) { こういう風に引数の closure に inline つけられないかやってみたけどダメでしたw
Avatar
↓単純な例での reducefor の比較やってみました。 https://github.com/koher/reduce-performance-test
Contribute to reduce-performance-test development by creating an account on GitHub.
Avatar
grid を作る処理を init から外に出して let grid = Matrix.generateGrid(a.rows, b.cols) { (i, k) in (0 ..< a.cols).sum { j in a[i, j] * b[j, k] } } return Matrix<R, n, p>(rows: a.rows, cols: b.cols, type: (a.type == b.type) ? a.type : .Default, grid: grid) ってしてみましたが変わらずでした( generateGrid@inline 化してある) (edited)
Avatar
func testReduce() { measure { XCTAssertEqual(ns.reduce(0) { $0 + $1 * $1 }, squareSum) } } func testForLoop() { measure { var result: Int64 = 0 for n in ns { result += n * n } XCTAssertEqual(result, squareSum) } } func testMapReduce() { measure { XCTAssertEqual(ns.map { $0 * $0 }.reduce(0) { $0 + $1 }, squareSum) } } (edited)
Avatar
このreduce、inout版ですか?
Avatar
あー、違いますね
3:18 AM
ただ、結果が Int64 なので
Avatar
影響ないか
Avatar
$ swift test -c release ... <unknown>:0: Test Case '-[ReducePerformanceTests.ReducePerformanceTests testForLoop]' measured [Time, seconds] average: 0.001, relative standard deviation: 45.967%, values: [0.002224, 0.000979, 0.000871, 0.000871, 0.000845, 0.000793, 0.000698, 0.000720, 0.000719, 0.000733], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 ... <unknown>:0: Test Case '-[ReducePerformanceTests.ReducePerformanceTests testMapReduce]' measured [Time, seconds] average: 0.003, relative standard deviation: 55.466%, values: [0.007914, 0.002837, 0.002468, 0.002463, 0.002313, 0.002383, 0.002317, 0.002413, 0.002338, 0.002334], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 ... <unknown>:0: Test Case '-[ReducePerformanceTests.ReducePerformanceTests testReduce]' measured [Time, seconds] average: 0.001, relative standard deviation: 5.212%, values: [0.000704, 0.000692, 0.000675, 0.000674, 0.000674, 0.000674, 0.000674, 0.000701, 0.000608, 0.000594], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 (edited)
3:20 AM
average の有効桁数が足りない・・・
3:23 AM
↑見づらいので↓ $ swift Welcome to Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36). Type :help for assistance. 1> extension Array where Element == Double { 2. var mean: Double { 3. return reduce(0) { $0 + $1 } / Double(count) 4. } 5. } 6> [0.002224, 0.000979, 0.000871, 0.000871, 0.000845, 0.000793, 0.000698, 0.000720, 0.000719, 0.000733].mean // testForLoop $R0: Double = 0.00094530000000000015 7> [0.007914, 0.002837, 0.002468, 0.002463, 0.002313, 0.002383, 0.002317, 0.002413, 0.002338, 0.002334].mean // testMapReduce $R1: Double = 0.0029779999999999997 8> [0.000704, 0.000692, 0.000675, 0.000674, 0.000674, 0.000674, 0.000674, 0.000701, 0.000608, 0.000594].mean // testReduce $R2: Double = 0.00066700000000000006
3:23 AM
おお、単純ケースでも reduce の方が速い。
Avatar
素晴らしい😁
Avatar
UnsafeMutablePointer 使ったらどうなるだろう?
3:25 AM
お、 Range じゃなくて Array にしたら testForLoop の方が速くなった?🤔
3:25 AM
若干だけど。誤差かなぁ。
3:26 AM
measure ってサンプル数増やす方法あるのかな?
Avatar
中でfor文回す?
Avatar
@tarunon それはできればやりたくないです😅
3:27 AM
いずれにしても mapreduce は大分遅そうですね。
Avatar
n = 1_000_000 ← この数を増やすんではダメ何です?
Avatar
forreduce は大して変わらなさそう (edited)
Avatar
Range じゃなくて stride だとどうです?
Avatar
n = 1_000_000 ← この数を増やすんではダメ何です?
オーバーフローします😇
Avatar
あ、なるほどw
3:28 AM
lazy.map.reduce だったら Array 作り直さずに済んで速くならないかとさっき思いました。
Avatar
演算の速度調べるだけなら &+&* にしてオーバーフローさせちゃってもいいんですけどね。
3:29 AM
.....<Array が作られてないんで大丈夫だと思いますよ。
3:29 AM
lazy より余計な処理が少なくて速そう。
3:30 AM
ああそうか、今 Range なんだから UnsafeMutablePointer もないな・・・。
Avatar
そう思ってlazy.map.reduceはためしたけど少しは早くなりますよ (edited)
3:35 AM
Any calls to a function marked @_transparent MUST be inlined prior to doing dataflow-related diagnostics, even under -Onone. This may be necessary to catch dataflow errors.
3:36 AM
transparentはmust inlineで-Ononeでも効く・・・?
Avatar
強い💪
3:36 AM
subscript とかはそうしちゃって良さそう。
Avatar
そう思ってlazy.map.reduceはためしたけど少しは早くなりますよ
え、ほんとに?
Avatar
はい。 @inlineable つけない状態での話しかも
Avatar
ああ
3:37 AM
lazy.map.reduce
Avatar
map.reduce vs lazy.map.reduce
Avatar
読み違えてた
3:37 AM
足してみます
Avatar
ただクロージャがガシガシつながる感じになるから、結局命令形ループには絶対届かないと思うんで、あまり深く追わなかった
3:40 AM
@inline(__always) Force inlining (at least at -O for now).
3:42 AM
@inline は本当にドキュメントが少ない・・・
Avatar
$ swift Welcome to Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36). Type :help for assistance. 1> extension Array where Element == Double { 2. var mean: Double { 3. return reduce(0) { $0 + $1 } / Double(count) 4. } 5. } 6> [0.007428, 0.000827, 0.000812, 0.000774, 0.000730, 0.000669, 0.000670, 0.000671, 0.000672, 0.000674].mean // testForLoop $R0: Double = 0.0013927 7> [0.001285, 0.001151, 0.001017, 0.001008, 0.000957, 0.000841, 0.000824, 0.000814, 0.000818, 0.000849].mean // testLazyMapReduce $R1: Double = 0.00095639999999999993 8> [0.008967, 0.003619, 0.003361, 0.003240, 0.003070, 0.003096, 0.003307, 0.003079, 0.003139, 0.003077].mean // testMapReduce $R2: Double = 0.0037955000000000003 9> [0.001513, 0.001253, 0.001021, 0.000973, 0.000968, 0.000928, 0.000814, 0.001816, 0.001165, 0.000897].mean // testReduce $R4: Double = 0.0011348
3:42 AM
有意差あるのかわかんないけど確かに lazy.map.reduce が速い
3:43 AM
これなら lazy.map.reduce 使うことで無駄に Array も生成せず、 reduce の中にごちゃっと式を書く必要もなく、最高のパフォーマンスも得られるってことで最高なのでは。
Avatar
入力が毎回違うのはなぜ?
Avatar
↑は swift test で計測された時間をコピペしたものです。
3:44 AM
swift test のままだと有効数字が足りなくて
Avatar
meanの性能を測ってるのかと思った。
3:44 AM
そゆことか。
Avatar
テストコードは↓。 func testReduce() { measure { XCTAssertEqual(ns.reduce(0) { $0 + $1 * $1 }, squareSum) } } func testForLoop() { measure { var result: Int64 = 0 for n in ns { result += n * n } XCTAssertEqual(result, squareSum) } } func testMapReduce() { measure { XCTAssertEqual(ns.map { $0 * $0 }.reduce(0) { $0 + $1 }, squareSum) } } func testLazyMapReduce() { measure { XCTAssertEqual(ns.lazy.map { $0 * $0 }.reduce(0) { $0 + $1 }, squareSum) } }
Avatar
lazyだと無駄な関数呼び出しは発生するから sigma の中に命令ループを書くのが一番良いと思います
Avatar
でも↑だと for より速いよ? (edited)
Avatar
謎ですね。
Avatar
nsはなんですか?
Avatar
自前ループより、標準ライブラリは最適化された何かになってるとか。
3:46 AM
private let n: Int64 = 1_000_000 private let ns = Array(0..<n) private let squareSum: Int64 = 333332833333500000
3:46 AM
あれ? Array にしたままだった
Avatar
ふむ
Avatar
Range に戻してみよう
Avatar
えーっと、デバッグビルドだと
3:47 AM
Rangeの場合だとなんですけど
3:47 AM
for - in を実行するために
3:47 AM
Sequence に対する protocol witnessがかかって
3:47 AM
next() の呼び出しで
3:47 AM
オーバーヘッドがあるんですよね
Avatar
swift test -c release です。
Avatar
リリースビルドでもそうなのかも。
3:48 AM
Sequeneに対してはmakeIteratorだから正確にはその返り値のIteratorProtocolに対するnext()
Avatar
でもさっきやったときは Range でも for より reduce が速かった。
Avatar
.map だとArrayに最適な内部表現になるということはありえる
Avatar
そのときは lazy を試してなかった。
Avatar
それだけ小さいコードでも差が出て来るのであれば、
3:49 AM
LLVMIRを見てみるか
3:49 AM
なんか良いスニペットできたらください
Avatar
Contribute to reduce-performance-test development by creating an account on GitHub.
Avatar
ちなみにこちらで var grid = Array(repeating: R.zero, count: a.rows * b.cols) for l in (0 ..< a.rows * b.cols) { let (i, k) = (l / b.cols, l % b.cols) var x = R.zero for j in 0 ..< a.cols { x = x + a[i, j] * b[j, k] } grid[l] = x } var grid = Array(repeating: R.zero, count: a.rows * b.cols) for l in (0 ..< a.rows * b.cols) { let (i, k) = (l / b.cols, l % b.cols) grid[l] = (0 ..< a.cols).sum{ j in a[i, j] * b[j, k] } } を比較すると 1: 53.226 msec. 2: 348.296 msec. となって、for を使った方が全然速い感じです。
Avatar
nsがArray/Range か , ループが for in か、 map.reduceか、lazy.map.reduce か、reduceだけか、があるのかな?
Avatar
(sum は sigma で、中で Range.reduce 使ってます)
Avatar
@Taketo Sano 僕の検証でもそうでした。Matrixのケースだと要素の型がジェネリック型になったりしてるんで、そのへんで状況が違う可能性はあるんですよね。
Avatar
なるほどなるほど。
3:52 AM
とりあえず今のコードあげます。
Avatar
@omochimetaru はい、その四つです。
3:59 AM
Array の map の実装ってみれたりするんですかね? ここでは見当たらなかった https://github.com/apple/swift/blob/master/stdlib/public/core/Arrays.swift.gyb
swift - The Swift Programming Language
Avatar
@omochimetaru > nsがArray/Range か ああ、これはどちらかだけです。 CountableRange で作ってて、たまたま Array にしてみて試してたら lazy 付けたときに戻し忘れただけです。
Avatar
(一旦抜けます🙇
Avatar
僕と @omochimetaru もちょうど今から社内会議ですね。
Avatar
なるほどw お疲れ様です👋 色々とありがとうございます🙇
🙂 1
Avatar
@omochimetaru ちなみに TimeProfiler で計測したときは、計測用に実行可能なアプリを作って繋いだんですよね? (edited)
Avatar
Contribute to SwiftyAlgebra development by creating an account on GitHub.
Avatar
了解です、ありがとうございます😊
Avatar
ヤバすぎる・・・ (edited)
5:11 AM
さっきの @koher のやつを試したんだけど (edited)
5:11 AM
最適化をかけると、コンパイラーが、 lazy.map.reduce 版の実装を (edited)
5:11 AM
forループ版の実装の呼び出しに差し替える。 (edited)
😮 1
5:11 AM
define hidden swiftcc void @_T01a17testLazyMapReduceyyF() local_unnamed_addr #0 { tail call swiftcc void @_T01a11testForLoopyyFTm(<2 x i64> <i64 ptrtoint ([18 x i8]* @4 to i64), i64 17>) #0 ret void }
5:11 AM
define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 { entry: store <2 x i64> <i64 0, i64 10000>, <2 x i64>* bitcast (%Ts14CountableRangeVySiG* @_T01a2nss14CountableRangeVySiGv to <2 x i64>*), align 16 store i64 100000, i64* getelementptr inbounds (%TSi, %TSi* @_T01a4loopSiv, i64 0, i32 0), align 8 call swiftcc void @_T01a11testForLoopyyFTm(<2 x i64> <i64 ptrtoint ([12 x i8]* @0 to i64), i64 11>) tail call swiftcc void @_T01a13testMapReduceyyF() call swiftcc void @_T01a11testForLoopyyFTm(<2 x i64> <i64 ptrtoint ([18 x i8]* @4 to i64), i64 17>) ret i32 0 }
5:12 AM
main関数は、ループ版、mapReduce版、ループ版 の呼び出しになる。 (edited)
5:13 AM
副作用として表示される文字列が違うが、その切替のための引数が追加されてなんかうまくやっている (edited)
Avatar
ってことは lazy で実装しとけば Matrix も早くなることが期待できる!?
Avatar
ループ版があったからこうなったのかわからないが、lazy.map.reduceがループにコンパイルされる可能性があるってことですね。。。
5:14 AM
$ swiftc -emit-ir -O a.swift > ir.txt ビルドは←
5:18 AM
計算自体が消去されちゃったのかな、副作用ありで書いてみる
5:20 AM
あー、ちょっと変えたら分離されたんで、忘れてください
👌 1
5:31 AM
ForLoopとLazyMapReduceはほぼ同じ性能で、
5:31 AM
IRを見てみると
5:31 AM
_T01a17testLazyMapReduceyyF ラベル: 30 -> 122 -> 128 -> 133 -> 140 -> 145 -> 35 -> 41 -> 46 -> 140 (edited)
5:31 AM
ラベルジャンプでのループに展開されている (edited)
5:32 AM
Intのオーバーフローチェックがガシガシ挟まってて見かけの分岐数がおおいw
Avatar
@_specialize について調べてます。 Matrix で大規模な計算をしたいのは今の所 R=Int, _n=Dynamic, _m=Dynamic のケースなんですが、 mul をこれに特化させることはできるんでしょうか?
Avatar
https://github.com/apple/swift/blob/master/docs/Generics.rst#specialization 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) } } できますね。
swift - The Swift Programming Language
Avatar
あ、こうか @_specialize(where T == Int, U == Float)
7:00 AM
やってみます!
Avatar
swift4でその丸括弧の中の記法が変わったとかいう噂もあるんで、コンパイル通らなければ標準ライブラリの中身をgithubで検索したりして真似ると良いかも。
Avatar
ktkr😝 original : 55.067 msec. imperative : 56.907 msec.
Avatar
おおw
Avatar
@_specialize(where R==Int, n==Dynamic, m==Dynamic, p==Dynamic) これで行けました!
Avatar
7秒かかってた3次元トーラスのホモロジー群が0.7秒で出るようになった😂
Avatar
数学が捗る
Avatar
誠に感謝です🙏
🙂 1
7:30 AM
各成分の積和の演算を Metal に投げて並列で計算させるというのもアリかと考えたりしました。
7:30 AM
全く generic でなくなりますが。
Avatar
MetalもあるしAccelerateもありますね https://developer.apple.com/documentation/accelerate
7:32 AM
where付きのextensionで、特定の型パラメータの場合だけ別の実装を与えることができるんで、
Avatar
前調べたときは確か Int 型の行列は対応してなかったような
Avatar
Floatだったらその手のアクセラレータを使うっていうのはできます
7:32 AM
ああ、Intは無いかも・・・?
Avatar
@t.ae と僕で作ってる TensorSwift では Float に限定して Accelerate を使ってますね。 https://github.com/qoncept/TensorSwift
TensorSwift - A lightweight library to calculate tensors in Swift, which has similar APIs to TensorFlow's
7:35 AM
TensorSwift - A lightweight library to calculate tensors in Swift, which has similar APIs to TensorFlow's
Avatar
前に Qiita に書いてた奴ですね
Avatar
↓で切り分けてて、 BLAS がない Linux 環境では通常の計算をしています。 https://github.com/qoncept/TensorSwift/blob/master/Sources/TensorNN.swift#L104
TensorSwift - A lightweight library to calculate tensors in Swift, which has similar APIs to TensorFlow's
Avatar
なるほどなるほど
Avatar
これのもっといいやつが swift-evolution で議論されてて
7:37 AM
どれだっけな・・・
Avatar
importできるかどうかでifになるやつですね
Avatar
前話してた import 可能化で
7:40 AM
そう、それ
Avatar
ああ、OSじゃなくてか。
Avatar
https://github.com/apple/swift/pull/11613 canImport? 8月末実装済みなのでたぶん4.1で入るかと。
This implementation required a compromise between parser performance and AST structuring. On the one hand, Parse must be fast in order to keep things in the IDE zippy, on the other we must hit the...
🙏 1
Avatar
おお、それです。
7:42 AM
4.1 で入るんですね。うれしい。
7:43 AM
Coming soon to a Swift compiler near you! 😂 (Thanks @CodaFi_ for implementing an old proposal, accepted May 2016!) https://t.co/D4jP5eaGUJ
Likes
197
Avatar
これは便利そう👍
7:44 AM
iOS と mac の universal 化捗りそう
Avatar
4.1ってリリース春でしたっけ?
7:44 AM
This post describes the goals, release process, and estimated schedule for Swift 4.1.
Avatar
2018前半ってざっくりw
7:45 AM
Swift 4.1 is intended to be released in the first half of 2018.
7:45 AM
これか。
7:46 AM
まあ、 Swift 5 のことも考えたら春頃ですかね?早く canImport 使いたい・・・。
Avatar
Javaみたくでるでる詐欺になる未来が
Avatar
これってそんなに古い Proposal だったんだ。新しい Proposal 眺めてても見つからなかったはずだ・・・。 https://github.com/apple/swift-evolution/blob/master/proposals/0075-import-test.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
7:50 AM
ああ、 Status も Status: Implemented (Swift 4.1) になってた。
Avatar
2016年末に一度実装されたんですが、もろもろ問題が発生して revert されたんです。https://github.com/apple/swift/pull/5778
SE-0075 requests that we offer a build-time check for the importability of modules. This check, however, is particularly expensive so we can no longer resolve every condition statically. Conditio...
Avatar
SE-0075 requests that we offer a build-time check for the importability of modules. This check, however, is particularly expensive so we can no longer resolve every condition statically. Conditio...
7:57 AM
パッケージ A を import したときだけ使えるパッケージ B の機能とかもできるなら複雑そう・・・。
8:03 AM
@Taketo Sano そういえば、SwiftyAlgebraはSwiftPM対応したライブラリにはしないんですか?
Avatar
@koher 最近の Swift 事情に疎くて…w 作り方知らないんですw
Avatar
めっちゃ簡単ですよ。パッケージ名のディレクトリ作って swift package init ってやればひな形が完成します。
Avatar
やってみます👍
Avatar
Xcode 用のプロジェクトは swift package generate-xcodeproj でできるんですけど、
8:06 AM
ポイントは .gitignore されてることで、リポジトリには含まれず、冪等になってることですね。
8:07 AM
Xcodeのややこしい色々な設定がignoreされてるんで、いつでも generate-xcodeproj でプロジェクトを作り直せばソースだけからキレイな状態を作れます。 (edited)
8:08 AM
(厳密には冪等になってなくて上書き時に変になったことがあった気がしたんで、僕はプロジェクト消してから作り直してますが)
Avatar
おそらくxcodeproj自体は作り直されているんだけど(だからxcode上で開いてたフォルダツリーが閉じ直されてだるい)
Avatar
ふむふむ、ちょっとやってみます。
Avatar
xcodeのビルド生成物の方がクリアされなくて
8:09 AM
前の構成のビルドの残骸が次のビルドで悪さをすることが起こってるような感じがしている
8:10 AM
安心と信頼のDerivedData全消し
Avatar
なるほど。 swift package clean もイマイチキレイになってないことがあったので .build 消してる。
8:10 AM
@Taketo Sano ビルドは swift build で走って swift test でテスト走らせられます。 Xcode からもできますが。 (edited)
8:11 AM
後は GitHub にコミットすれば SwiftPM で簡単に import できるようになります。コマンドラインから使うときとか便利。
8:12 AM
swift-package-manager - The Package Manager for the Swift Programming Language
Avatar
了解です、やってみます!
👍 1
8:22 AM
とりあえず一連の行列演算の高速化については、 1. map.reduce は一つの関数にまとめて @_inlineable 2. subscript は @_transparent 3. mul を @_inlineable, かつ R==Int の場合 @_specialize で対応することにしました。元の > 7,000 msec から 55 msec まで高速化して感動です、ありがとうございます😂 https://github.com/taketo1024/SwiftyAlgebra/commits/master (edited)
Contribute to SwiftyAlgebra development by creating an account on GitHub.
👏 3
8:24 AM
一人じゃ絶対無理だったので助かりました😭
Avatar
100倍以上、すごい
Avatar
Xcode 上で -Ounchecked でビルドすることってできるんでしょうか?
Avatar
Project->BuildSettings->Optimization Level で出来たと思います
11:21 AM
ありゃ、選択肢に無いな
Avatar
//:configuration = Debug //:configuration = Release //:completeSettings = some SWIFT_DISABLE_SAFETY_CHECKS
11:22 AM
Disable Safety Checks が
11:22 AM
これのことな気がする?未調査
Avatar
おぉ、それっぽいですね
Avatar
Kishikawa Katsumi 10/23/2017 11:24 AM
SWIFT_OPTIMIZATION_LEVEL (Optimization Level )にテキストで -Ounchecked と入れたらいいですよ。 (edited)
Avatar
おっ、ありがとうございます🙏
Avatar
Kishikawa Katsumi 10/23/2017 11:26 AM
念のため、配列の外にアクセスしてみてクラッシュしなければ効いています。
Avatar
無視されるようになるのは配列外参照, !, preconditionでしたっけ、他にあるかな
Avatar
as!とかtry!とかもかなあ
Avatar
それはなんか!の範疇のイメッジ
Avatar
@Kishikawa Katsumi SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; がはじめから入ってるんですが、別のフラグだったりしませんか?
Avatar
-Oxxxx の仲間が何種類かあります
Avatar
並べて書けばいいのかしら?
Avatar
多分。
11:43 AM
xcodeのビルドログのところに個別のコンパイルコマンドが出ているので
11:43 AM
そこに -Ounchecked が含まれて入れば成功です (edited)
Avatar
オーバーフローも無視されるようになります。
Avatar
ダメっぽいですw
11:44 AM
Int のオーバーフローチェックを計算のたびやってるのがオーバーヘッドになっちゃいないかと疑ってみまして。
Avatar
Kishikawa Katsumi 10/23/2017 11:45 AM
それはどれか1つしか書けないです。 -Owholemodule を上書きします。
Avatar
そうすると whole module optimization が無効になったりはしないんです?
11:46 AM
55msec が 3.457 sec になってしまいましたw
Avatar
$ swiftc -whole-module-optimization -Ounchecked -O a.swift
11:48 AM
↑これが通るので、その欄のところはそのままにして
11:51 AM
あ、ながすぎてコピペできねえ
11:51 AM
Disable Safety ChecksをYESにしたうえで
11:51 AM
Releaseビルドなら
11:51 AM
-Ounchecked が挿入されました。
Avatar
おぉ👍
Avatar
Kishikawa Katsumi 10/23/2017 11:51 AM
User definedに SWIFT_WHOLE_MODULE_OPTIMIZATION = YES でもOK
11:52 AM
^ SWIFT_OPTIMIZATION_LEVEL-Ounchecked
11:53 AM
それで swiftc -incremental -whole-module-optimization -module-name TargetApp -Ounchecked -DDEBUG -D ... こうなるところまで確認しました。
Avatar
おぉ、ありがとうございます。
11:55 AM
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc -incremental -module-name SwiftyAlgebra -Ounchecked -whole-module-optimization @omochimetaru さんのやり方で -Ounchecked 入りました👍
11:55 AM
55msec が 44msec になりました👍w
Avatar
結構減りますね
11:56 AM
足し算と掛け算のたびに分岐してるからか
Avatar
計算の度に分岐してたらもっと減りそうだけど、それくらいしか減らないのか🤔
Avatar
分岐予測が効いてそう
Avatar
if文入れるとかよりはオーバーヘッドが小さい?
12:38 PM
分岐予測ってそんなに効くのか…。
12:38 PM
普通のbrですけど
12:39 PM
@koher 分岐予測は、分岐先の未来を投機的に計算するので
12:39 PM
予測が当たっていて、メモリアクセス待ちとかで追いつく場合だと
12:39 PM
時間的ロスが無いはず
Avatar
なるほどー、待ち時間の空きで計算しておくのか。
Avatar
分岐予測が失敗して無駄になった時間は、パイプラインのフェッチステージから実行ステージまでの段数に等しい。最近のマイクロプロセッサではパイプラインは非常に長く、分岐予測が失敗した場合の遅延は10から20クロックサイクルとなる。パイプラインが長くなるほど、分岐予測の精度が要求されるようになる。
1:09 PM
CPU自体がパイプライン化されているから
1:09 PM
1クロックあたりの性能ってもうよくわからなくなってて
1:09 PM
スペックとかは統計的な話だったはず
Avatar
The last commit is me kinda sorta maybe guessing at what substitutions/ProtocolConformances need to be glued together, in a way that works in some cases... but doesn't even compile the standard lib...
1:56 AM
CondConfそろそろかしら
Avatar
はやく!
Avatar
I would like to propose the following change to the standard library: deprecate `Sequence.flatMap<U>(_: (Element) -> U?) -> [U]` and make this functionality available under a new name `Sequence.filteredMap(_:)`.
5:59 AM
Optional版のflatMapをfilteredMapに改名しようってメール来てる
6:04 AM
struct Person { var age: Int var name: String } func getAges(people: [Person]) -> [Int] { return people.flatMap { $0.age } }
6:04 AM
mapと間違えてflatMap使いつつ Optionalアップキャストして動いちゃう話
Avatar
うーん、 mapflatMap 間違えるというのは・・・ (edited)
6:06 AM
わかりづらいというのはわかる。
Avatar
func getNames(people: [Person]) -> [String] { return people.flatMap { $0.name } } (edited)
6:07 AM
StringがCollectionだから↑が正当って話しも出てくるけどこっちについては英語の意味が取れなかった。。
6:12 AM
レスは賛成が多い。
Avatar
mapflatMsap は使い間違えないけど、二つの flatMap がわかりづらいというのはわかるから、変更するのはなしじゃないとは思う。
Avatar
これがflatMapだってわかったときはすごくわかった感があったけど
6:14 AM
すごくわかった感がある時点でわかりにくい話ではある
Avatar
Optionalの暗黙キャストやめればええんやで
👏 1
6:27 AM
レスポンスしてみようかな
Avatar
それは影響範囲が大きすぎて受け入れられなさそうな気が・・・
Avatar
受け入れられないのは承知の上ですが、そういう議論があるというのを認知してもらえるのが目的なので (edited)
Avatar
暗黙変換絶許マンと化した @tarunon (edited)
Avatar
Optional の暗黙キャストが多くの問題を招いているのは間違いないですからねぇ・・・
Avatar
議論出して、同調する人がどれくらいいるのかも気になる
Avatar
これが filteredMap になる場合
6:30 AM
高階型の道からは完全に外れるよね
6:30 AM
flatMapのほうはdeprecatedになるらしいし。
Avatar
もう一つは
6:31 AM
Sequence.from(optional Element?)って言う変換オペレーター作って
6:31 AM
明示的に変換していくのはありだと思う
👍 1
Avatar
一旦Arrayを通すってことね
Avatar
そう
Avatar
$0 ? [ $0! ] : [] ←これだよね (edited)
Avatar
それはちょっとあれだけどまあそう
Avatar
$0.map { [$0] } ?? []
Avatar
そっちのほうが好き
Avatar
びっくり消せた
6:33 AM
ウーム
Avatar
エイヤ
Avatar
とんできた
Avatar
これが filteredMap になる場合 高階型の道からは完全に外れるよね
これなんで?
Avatar
高階型を使うことで、 OptionとArrayとみなして ArrayとArrayのflatMap みたいに実装をまとめられるんじゃないかと思ってるんだけど違うかな
7:17 AM
Array.flatMap( T -> U?)と、Array.flatMap ( T -> [U]) を、そもそも一つにできるのかなあと
7:17 AM
でも名前が変わっちゃうならまとめようがないから。
Avatar
Array がモナドとすると flatMaptransform の戻り値は Array のみでないといけない(任意の SequenceCollection ではいけない)と思う。 (edited)
Avatar
うーんたしかに Promiseが戻ってきた場合とかどうにもならないなあ
Avatar
今も Array に限ってないのか。
Avatar
はい。いまはOptional返せる版のオーバーロードがあるよねっていうのが
7:23 AM
そもそもの話。
Avatar
func flatMap<SegmentOfResult>(_ transform: (Self.Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence https://developer.apple.com/documentation/swift/sequence/2905332-flatmap
7:23 AM
Array じゃないといけないのかと思ってた。
7:23 AM
戻り値が Array なだけか。
Avatar
任意のElementが同じ型のSequenceなら変換可能で、その括りで行くとOptionalも変換可能なはずだ、という発想だと思う (edited)
Avatar
OptionalSequenceにしてしまえば…
Avatar
やばそう
Avatar
なるほどw
7:53 AM
Tは暗黙でT?になるから暗黙でSequenceに
Avatar
map とかがヤバイですね。
Avatar
@tarunon
Instead, I think Nobuo Saito is right, and that a renaming to filteredMap is only fighting symptoms, and not the cause (but I’m not that sure if there’s a good way to tackle the cause).
1:38 AM
嬉しい反応
Avatar
symptomsって症状でcauseって原因だから、 対処療法的であって根本治療ではない って言ってる感じか
1:41 AM
nilを取り除くのに flatMap なんて名前付けるのはおかしいだろって意見に対して、↑の人が、Optionalは要素1のArrayとみなせるからなんだよって言っている
Avatar
一回警告出るようなパッチ当てたけど外したとのこと。
Due to implicit promotion to optional it is possible to call flatMap with a closure, that does not return an optional. This way the code works, but is unnecessary inefficient. Such uses of flatMap ...
GitHub is where people build software. More than 25 million people use GitHub to discover, fork, and contribute to over 69 million projects.
1:56 AM
これはflatMap(E->T)をオーバーロードしてdeprecatedつけてるね。かしこそう。
Avatar
The following code behaves incorrectly due to the presence of this overload. let a: Int = 1 let b: Int? = 2 let c: Int? = nil let result: [Any] = [a, b, c].flatMap { $0 } Fixes: rdar://problem/3191...
2:00 AM
やっぱり外した話がよくわからんのだけど、左辺が [Any] なのが関係あるんかな
Avatar
左辺がAnyで推論されて
2:01 AM
それが伝搬して[Int?].flatMap { $0 } じゃなく [Any].flatMap { $0 }になってしまったものと思われる
2:01 AM
これに関しては一貫してArrayの暗黙キャストが悪だと訴えたい
2:02 AM
とはいえ[Int, Int?, Int]のArrayならキャスト無しなら正しくは[Any]になるはずか。
Avatar
[Any].flatMap { $0 } これは、 Any から Any? へのアップキャストが生じるってこと?
Avatar
いや
2:02 AM
多分このオーバーロードが存在することで
2:03 AM
[Int?].flatMap { $0 } -> [Int]これが期待される場面で、[Any].flatMap { $0 } -> [Any]が優先されるようになってしまったんだと思う
Avatar
ああなるほど
2:07 AM
.someへの昇格に警告を入れてるんじゃなくて、mapのシグネチャの flatMap ( E -> T ) -> [T] を警告用に足すアイデアだったから
2:07 AM
そっちが余計に選ばられるケースが稀に存在するのか
2:07 AM
しんどいな・・・
Avatar
本当だ、Optionalへの暗黙変換よりExistentialへの暗黙変換のほうが優先されるんですね〜 https://github.com/apple/swift/blob/master/lib/Sema/ConstraintSystem.h#L446-L449
swift - The Swift Programming Language
Avatar
こんなふうになってるんですね
2:29 AM
Score::operator < で、↑のenumの若い順に優先比較している
Avatar
Optionalへの暗黙変換よりExistentialへの暗黙変換のほうが優先
型システム上の辛みがありそう・・・。
2:31 AM
Any はあらゆる型のスーパータイプなので自然なアップキャストだけど、 Optional は暗黙の型変換だから、どちらが優先されるべきか議論の余地がありそう。しかも、 Swift の Optional はスーパータイプ的に振る舞うから・・・。
2:32 AM
↓ができるとことか。 let a: () -> Int = { 42 } let b: () -> Int? = a // OK (edited)
Avatar
僕の議論はそれはダメでしょ警告だそうよというところ
Avatar
↑も禁止して暗黙の Optional 変換も止めてしまった方がシンプルなのは間違いない。
Avatar
flatMap vs map confusingもこいつが原因
Avatar
Optional を tagged union で実現したのに、 untagged union のように振る舞わせるというところのヤバさ・・・。
2:35 AM
そりゃどこかに歪みが出る。
Avatar
昔の言語で 1 + "2" ができて便利だと思ったけど現代では否定されているように
Avatar
うん
Avatar
Evolutionに突撃してくれ!
Avatar
この手の型システムも硬い方がいいじゃんって話になっていきそうな気がした
Avatar
やっぱこういう場当たり的な便利そうなのはやらない方がいいんだなぁ。この前の asyncthrows を分離しておいた方がいいのと同じように。
Avatar
たるのんが突撃するんじゃないの〜🙄
👋 1
Avatar
もうしただろ!!!
2:36 AM
でもこの場合って、Evolutionの実装作るルール的には僕がOptinonal警告作ることになるのかな
Avatar
いや、この議論は、Swift6を見据えた長期計画として根本的にスレ建てして
Avatar
仮に通ったとして
2:36 AM
あー
Avatar
関連する全問題点を叩きつける感じじゃないと
2:37 AM
いまさら変えられないと思うよ
Avatar
なるほどね
Avatar
一個のトピックだけだと泥沼にしかならないと思うし、全体としての調和の問題もあるから・・・
Avatar
かなり望み薄だけど、 Swift 6 を逃したら半永久的にできなさそう。
2:38 AM
暗黙の Optional 変換の廃止というトピックで。
2:38 AM
ついでに if let の構文も変えてほしいけど。
Avatar
パワのあるトピック名だ
Avatar
そうなんですよね if let がなんか変
Avatar
ちょっと纏めてみるか
Avatar
おお
Avatar
てかこういうのはScala民の方が得意なんじゃないですかね @Biacco42 @ukitaka
😇 2
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
2:41 AM
よくあるリジェクト
Use pattern-matching in if let instead of optional-unwrapping:
2:41 AM
これ該当してるかな if letの話
2:42 AM
Optional implicitly promotion の話はここには乗ってないっぽそう
Avatar
Use pattern-matching in if let instead of optional-unwrapping:
って、リジェクトというか普通にできるくない? let n: Int? = 42 if case let n? = n { print(n) // 42 }
(edited)
Avatar
あ、リンク先のメールを見たら
Avatar
↑が一番マシな unwrapping だと思うけど、 case がめんどい・・・。 (edited)
Avatar
[swift-evolution] Obsoleting if let
2:45 AM
> Data point (which Chris brought up already, I think?): We tried this* and got a lot of negative feedback. Optionals are unwrapped too often for people to be comfortable writing "if let name? = optionalCondition”. Yes, I even implemented this and it was in the compiler for awhile, then later ripped it back out. You can find the history in git. I would guess that this all happened in ~March 2015. -Chris
2:46 AM
昔は if let name? = hoge という書式が書けたけど
2:46 AM
取り除いたよ ギットの歴史で2015年以前にあるよ クリス
2:47 AM
この話はあくまで if let とパターンマッチの並用であって、 if case let は別の話っぽいですね。
Avatar
なるほど。
2:49 AM
まあ if letif case let foo? = に入信すればいいんだけど、暗黙型変換は取り除いた方が将来のためではあると思う。その代わり初心者にはやさしくなくなるかなぁ。↓できなくなるし。 let a: Int? = 42 // NG let a: Int? = .some(42) // OK
Avatar
let a: Int? = .some(42) // OK になった瞬間に null安全アンチ派 がアップを始めそうだな (edited)
Avatar
でも前者を許しちゃってるから最初混乱したし、やっぱ暗黙の型変換が諸悪の根源な気がする。
Avatar
邪悪さにレベルがあって
2:51 AM
関数の暗黙変換が一番邪悪なので、こいつだけは絶対頃す
Avatar
null安全アンチ派 がアップを始めそう
Kotlinとかみたいな untagged union による null safety だったら問題にならないけどね。
Avatar
()->T => ()->T?と、(T?)->() => (T)->()
Avatar
union type なのか ADT なのか フワフワしてんのがいかんのかな
Avatar
確かに関数の暗黙変換だけなら潰せるかも。
Avatar
この二つは差し違えても頃す
Avatar
それは自分でクロージャ書いて変換しろってこと?
Avatar
クロージャ書くか、asで明示
Avatar
なるほど。
Avatar
でなければ警告
Avatar
警告でいいのか
Avatar
ぶっちゃけ警告で良いとは思っていて
Avatar
なんかそれのせいでコンパイル遅そうだよね
2:53 AM
モナドチェーン的な時。
Avatar
まあ段階踏むべきって言う話
2:53 AM
最初は警告、次にエラー
Avatar
ww
2:53 AM
その次はコンパイラクラッシュで
Avatar
警告に民が慣れて書かなくなってきたら廃止する
2:53 AM
それはコンパイラが負けてるからダメ
Avatar
民いうなw
2:54 AM
はい
Avatar
おや?↓はコンパイルエラーになってる。 class Animal { func foo() -> Int { return 42 } } class Cat: Animal { override func foo() -> Int? { return nil } }
2:55 AM
ああ逆か?
Avatar
@objcでは
Avatar
逆では?
2:55 AM
それだとAnimalとしてあつかったときになぜかnilが出る
Avatar
逆だった。
Avatar
逆か
Avatar
返り値については継承して狭められる
Avatar
class Animal { func foo() -> Int? { return nil } } class Cat: Animal { override func foo() -> Int { return 42 } }
2:56 AM
普通に通った。
2:57 AM
関数の暗黙の型変換潰すならこいつも潰さないと・・・。
Avatar
継承については明示変換ができないからなあ
Avatar
そもそもその継承、ウソなので殺したい
Avatar
class AnimalSpawner { func spawn() -> Animal } class CatSpawner : AnimalSpawner { func spawn() -> Cat } 嘘ではないよ (edited)
Avatar
↓これもいけた。 class Animal { func bar(_ x: Int) -> () { print("Animal") } } class Cat: Animal { override func bar(_ x: Int?) -> () { print("Cat") } }
Avatar
お、Javaではできないやつですね
Avatar
いや、 Optional はスーパータイプじゃないから嘘。
Avatar
引数側コントラバリアンス
2:59 AM
あ〜そういういみか。
Avatar
T?がTのサブタイプがウソなので継承は出来ないという論調
Avatar
なるほど。
Avatar
T?がTのサブタイプがウソ
これにつきる
3:03 AM
逆?
Avatar
TがT?のサブタイプなんじゃね
Avatar
ですね
Avatar
ウソがウソになってる
Avatar
すまん
Avatar
ややこしい
Avatar
にしても T? と T は別の型なのでどう考えてもおかしい
Avatar
プロポーザル書こう
Avatar
殺すなら Optional 暗黙変換すべて殺すほうがという気持ちなので厳しい…
3:08 AM
nullability っぽい振る舞いとごちゃまぜなんだなぁ
Avatar
@Biacco42 その通りなんだけど、 Kotlin 等の言語では T?T のスーパータイプは正しいんよね。で、 enum になっててネストできるとこと、スーパータイプでアップキャストで代入できるとこと、両方のいいとこ取りをしようとしたから歪みが出てる。
3:10 AM
nullability っぽい振る舞いとごちゃまぜなんだなぁ
同じこと言ってた
3:11 AM
Kotlin の Any?Any のスーパータイプなのも闇を感じるけど・・・
😇 1
Avatar
ですね
Avatar
Ceylon だと T?T のスーパータイプだけど Anything がトップタイプ(すべてのスーパータイプ)になっていて素晴らしい。
3:13 AM
Anything が sealed でサブタイプが Object or Null に限定されていて、 T?T|Null のシュガーだから、 Anything? == Anyhing|Null == Anything になる。
Avatar
Ceylon は Union type あるのかそういえば
Avatar
Kotlin も↓をすれば Ceylon と同じになる。 typealias Anything = Any? typealias Null = Nothing?
Avatar
Array<Array<Element: Equatable>> に対する extension って書けないですか?
Avatar
最近思ってたけどそれ書けない気がする。
Avatar
仕組み上できるかどうかより、構文が足りてない気がする。
Avatar
extension A where E == String {} はできるけど extension A where E == Array<T> {} ができない
9:46 AM
== の右辺に、ジェネリック型を書けない。
Avatar
Kishikawa Katsumi 10/25/2017 9:47 AM
extension Array where Element: Equatable これとは違うんですか?
Avatar
extension A where E == Optional<T> とか。 でも、プロトコルにしてやればいけるから、 @koher のケースは Element : Sequence じゃだめ?
Avatar
extension の構文って変で、↓のようであるべきな気がする。 extension Array<T> where T: Equatable { ... }
Avatar
ジェネリックパラメータ付きエクステンションは Generic Manifesto に乗ってますよ。
9:48 AM
実装待ち・・・
Avatar
@Kishikawa Katsumi あ、これそのものがやりたかったというわけではなく、似たようなケースの extension が書きたくて、一般的にこういうことってできなさそうだなぁと。
Avatar
あ、そうじゃないのか、それは Array自体の<T>か。
9:48 AM
その表記だと <T> 冗長じゃないですか? Array < >の型パラは .Element でアクセスできるから
Avatar
// 今 extension Array where Element: Equatable { ... } // 望ましい形 extension Array<T> where T: Equatable { ... } じゃないかと。
9:49 AM
↑ができるなら
9:49 AM
extension Array<Optional<T>> where T: Equatable { ... }
9:49 AM
とかもできる
Avatar
そういうふうに直さなくても
9:50 AM
extension <U> Array where Element == Optional<U> { }
9:50 AM
これで既存構文と調和した仕様にできる
Avatar
あと、この記法の良いところは型パラメータ名が変更されてもコードの修正が必要ないこと。
9:51 AM
↑Parameterized ExtensionとしてGeneric Manifestoに出てくる。
Avatar
Swift 1 から 2 のとき(だっけ?)に Optional<T> から Optional<Wrapped> に変更されて死体の山が。
Avatar
うーんでもそれだと
9:51 AM
型パラ5つとるジェネリック型において
9:52 AM
第2型パラにしかconstraintで言及しない場合に
Avatar
なるほど
9:52 AM
確かに。
Avatar
第1, 3, 4, 5が冗長で
9:52 AM
SwiftのプロトコルvsJavaのジェネリクスの初期の議論に戻る気がする。
Avatar
extension Array where Element: Sequence, Element.Element: Equatable { }
Avatar
@norio_nomura それでいけますよね
Avatar
Optional だとダメですよね?
Avatar
ただ 、 Sequence プロトコルは書けるけど、 Array<U> にはできない
9:53 AM
Optionalもプロトコルじゃないからだめで
Avatar
今本当にやりたいのは自作のジェネリック構造体なので・・・。
Avatar
OptionalProtocol ハックが必要
9:53 AM
自作のジェネリック構造体のケースならそれのプロトコルも定義すればいけますよ
Avatar
そうするとライブラリにそのためだけの不要なプロトコルが増えてしまう・・・
Avatar
なるほど。
9:55 AM
その場合extensionを諦めてトップレベル関数で・・・
Avatar
Parameterized extensions を待つしかないか・・・
9:56 AM
すべて gyb で解決したくなってきてよくない。
Avatar
今の話しGYB役に立ちます?
Avatar
現実的な組み合わせが列挙できる場合は
Avatar
あ〜
9:57 AM
Uを焼くのか。
Avatar
プロトコルの制約やめてすべて書き下してしまえばいい
Avatar
typealias NestedArray<T: Equatable> = Array<Array<T>> extension NestedArray { static var test: String { return "test" } } NestedArray<Int>.test // "test
Avatar
?!
10:03 AM
これ裏技では?
Avatar
ウッソwwwwww
Avatar
↑ができるなら Parameterized extensions すぐ実現できそう・・・
Avatar
え、なにこれは
Avatar
typealias OptionalArray<T> = Array<Optional<T>> extension OptionalArray { func filterNil() -> Array<T> { // use of undeclared type 'T' return flatMap { $0 } } }
10:06 AM
だめだ〜
10:06 AM
typealiasの左辺についてる型パラメータがルックアップできない
Avatar
typealias OptionalArray<T> = Array<Optional<T>> extension OptionalArray { func flatten() -> Array<Element.Wrapped> { return self.flatMap { $0 } } }
10:07 AM
だめだった
Avatar
alias右辺の型名も拾えないのか
10:07 AM
惜しいっ・・・
Avatar
Sequenceだとinitが生えて無くてArrayにできないけど
10:24 AM
Arrayを構成してるprotocolのうちのどれかがinit定義してるんで、それで縛れば生成可能になる
Avatar
話がみえない
Avatar
ただ 、 Sequence プロトコルは書けるけど、 Array<U> にはできない Optionalもプロトコルじゃないからだめで
10:26 AM
これだけ見てinitがしたいのかなって思った
Avatar
なるほど
10:28 AM
Array<U> ってのは
Array<Array<Element: Equatable>> に対する extension って書けないですか?
の内側のArrayのことで、具体的に何がしたかったのかは気にしていなかった
Avatar
なるほど
Avatar
Array < Array <> > の場合ならSequenceでいいけど、koher が聞きたかったのは そもそも Arrayの話じゃなくて、一般系としてArrayをあげただけだった
Avatar
typealias NestedArray<T> = Array<Array<T>> where T: Equatable コンパイル通るけどwhere句働いてないな
Avatar
なんやそれw
Avatar
typealiasにwhere句書いても働かない、単純に書いても通るのはバグか
Avatar
パーサーがガバく拾ってるだけみたいなやつかな
Avatar
ぽい
Avatar
Tへの制限にはなってますね。 let a = NestedArray<Array<Int>> // error: type 'Array<Int>' does not conform to protocol 'Equatable' // let a = NestedArray<Array<Int>> // ^
Avatar
生成時だけか
11:39 AM
11:43 AM
typealias NestedArray<T> = Array<Array<T>> where T: Equatable extension NestedArray { var hello: String { return "hello" } } [[(), ()], []].hello // OK!! let x: NestedArray<Void> = [[(),()],[]] // compile error
11:43 AM
Avatar
なるほどw
Avatar
NestedArray<Void>は存在できないが、extensionは正常に判定されていない
11:46 AM
11:46 AM
typealias NestedArray<T> = Array<Array<T>> where T: Equatable extension NestedArray { var hello: String { return "hello" } } [1, 2, 3].hello // OK!! [[(), ()], []].hello // OK!!
11:46 AM
オイオイオイオイ
11:47 AM
これはとんだ嘘つきextensionですね、
11:47 AM
typealiasのextension書けるのがバグっぽいな
11:51 AM
つまり、
11:52 AM
extension NestedArray // これはウソでコンパイラはextension Arrayと解釈していて where Element.Element: Equatable // 当然ArrayはElement.Elementなんて持ってないのでコンパイルエラー ということか (edited)
Avatar
夕食食べて風呂入りながら↑使ってもしかして Conditional Conformance もどきができないかと夢見てたのに完全に打ち砕かれてた。
🙇 1
Avatar
これが動くならParameterized extensionsも動いてるはずだよね
Avatar
ですよね。
Avatar
↓ってなんでできるんですっけ? (+)(2, 3) // 5 今って+ って関数じゃなくて static func ですよね?
Avatar
()で括るとinfixが消えてただの二引数関数になる?
Avatar
逆に Int.+(2, 3) とか Int.(+)(2, 3) とかできないんですが、明示的に型指定して static func な演算子にアクセスする方法ってありますか?
Avatar
(+) as ((Int, Int) -> Int)
2:09 PM
これかな?
2:09 PM
ちょっと手元に手頃なコンパイラがない
Avatar
はい、 infix func() で囲んで識別子化は Swift 1 の頃から出来たんですが、
2:09 PM
static func になった今でもできるのが不思議なのと、逆に static func っぽくアクセスする方法が見つからないのと。
Avatar
嘘つきエクステンションわろた
Avatar
↓はできました。一応これで指定できるのか。釈然としないけど・・・。 ((+) as (Int, Int) -> Int)(2, 3)
Avatar
オーバーロードした関数/変数をそれとしてアクセスするときにasで明示できるので、応用できそうだと思ったけど正解だった
Avatar
(Int, Int) -> Int+ は↓これだと思うんだけど、演算子は static func として宣言されても global な funcのように振る舞うのかな?よく考えたら 1 + 2 だってどうやって static func として解決されてるのかよくわからないし。 https://developer.apple.com/documentation/swift/numeric/2884921
Avatar
operatorはstaticになってもglobal扱いぽいですね
2:14 PM
コンパイラが頑張って展開してそう
2:15 PM
Equatableが中外どちらでも書けるので、両方統一して解釈してるのかなーと思いました
Avatar
昔、 global から static func に変える Proposal ありましたよね、確か。
Avatar
ジェネリックなときに少しタイピング量が減るのかな
Avatar
型パラを共通化できるから減る
Avatar
そういう意図で書いた↑
Avatar
ネストした型と同じメリットだ
Avatar
使うときの名前解決がトップレベルと変わらないなら定義するときにちょっと便利ってぐらいだよなあ
Avatar
でこの延長線上に、recursive constraintがありそう
Avatar
#swtws の発表内容を記事にしました。 > Swift に導入予定の Ownership 機能の紹介 by @omochimetaru on @Qiita https://t.co/6BZVoKs1mg
👏 5
Avatar
Swift って a -1 ってエラーになるのか。 $ swift Welcome to Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36). Type :help for assistance. 1> let a = 42 a: Int = 42 2> a -1 error: repl.swift:2:2: error: consecutive statements on a line must be separated by ';' a -1 ^ ;
2:00 AM
a - 1 じゃないといけない。
Avatar
a-1 はいけませんか?
Avatar
prefixにかぎらず二項演算はぜんぶそうですね。
Avatar
a-1 はいけると思う。
Avatar
ですよね
Avatar
いけた。 2> a-1 $R0: Int = 41
Avatar
a -1 は実際、 a-1 が、演算子無しで並べられているように見えるし、良いルールだと思ってる (edited)
Avatar
そうだね。
2:01 AM
今 typo でスペース入れ忘れたのが検出された。
Avatar
obj-c - (void)setupCellWithEntry:(id)object isRegistered:(BOOL)isRegistered labelTitle:(nullable NSString *)labelTitle labelSizeText:(NSString *)labelSizeText { cell.setupCell(withEntry: entry, isRegistered: isEntryRegistered, labelTitle: labelTitle, labelSizeText: labelSizeText) どうでもいいことだけど、SwiftよりもObj-Cの方が好きな数少ないところの一つは関数を引数ごとに改行するときに、Obj-Cは : の場所を合わせてくれるのがいいと思うんですよね、Swiftの左寄せよりは
Avatar
あー、 : が揃うのは僕も好きだった
Avatar
第一引数より前で改行した方が好き
2:50 AM
インデントが揃う
Avatar
そう言うXcodeのプラグインとかないかね
Avatar
(と第一引数の間に改行
Avatar
cell.setupCell( withEntry: entry, isRegistered: isEntryRegistered, labelTitle: labelTitle, labelSizeText: labelSizeText) こんな感じ?
Avatar
後ろの括弧も改行っすね
Avatar
なるほど
Avatar
他のIDEだとそういう改行ポリシー結構カスタマイズできたりするけどね
Avatar
引数にクロージャ入れたときに、クロージャの閉じ括弧のインデントが揃えばかなり綺麗なんだけど、そこだけ汚くなるから手で治しがち
Avatar
メソッドの. の前で改行するといいかんじになるよ (edited)
Avatar
UIView.animate( withDuration: duration, delay: 0.0, options: .curveEaseInOut, animations: { self.alpha = 0.0 }, completion: { _ in self.isHidden = true } ) 本当はこうしたい
2:56 AM
これ.前で切ってもクロージャの閉じ括弧は崩壊する
Avatar
クロージャが短ければワンライナーで終わらせる()
Avatar
まあそれはw
2:57 AM
UIView.animate( withDuration: duration, delay: 0.0, options: .curveEaseInOut, animations: { self.alpha = 0.0 }, completion: { _ in self.isHidden = true } ) なおXcode君激オシのインデントはこれ
2:57 AM
ちょっと。。。ね。。。
Avatar
import UIKit let duration = Float(1.0) UIView.animate( withDuration: duration, delay: 0.0, options: .curveEaseInOut, animations: { print(1) }, completion: { _ in print(2) })
Avatar
XcodeのSwift用Editorは本当バカな子だよな
Avatar
こうやって、クロージャの綴じカッコを、最後の文にくっつけると
2:58 AM
きれいになるよ。
Avatar
ないっしょw
Avatar
いやでも、このルールのもとなら
2:58 AM
そもそも閉じてるかどうか気にする必要ない
2:58 AM
インデントがきれいなら閉じてるってことだから。
Avatar
なるほどな
Avatar
僕も開きカッコ後と閉じカッコ前改行派だなぁ。
Avatar
Xcode君のインデントにコントリビュート出来ないかな
Avatar
Xcodeのインデントきれいになるには↑みたいなコツがいくつかあるけどマスターすると結構いい感じ
3:02 AM
コピペすると自動インデントされたりするから、手でスペース入れて直したりしてもそういうので壊れちゃうから
3:02 AM
もうXcodeに魂をうることにした
Avatar
えー
3:02 AM
Xcode のインデントは耐えられない。クロージャ周りひどいし。
Avatar
わかる >クロージャ周り
Avatar
AppCodeってそのへんどうなんですかね
3:03 AM
idea見てる限りだと期待できそうですが
Avatar
そういえばみなさん guard の条件文が長くて改行するときのインデントってどうしてますか?
Avatar
長くしない方法考えてる
Avatar
例えば guard let a = a, let b = b, let c = c else { doSth() } みたいな
Avatar
guard let xxxx, let xxxx, fooIsEnabled else { .... } こんな感じ (edited)
3:07 AM
else忘れてたわ
Avatar
var a: Int? = nil var b: Int? = nil var c: Int? = nil func main() { guard let a = a, let b = b, let c = c else { print(2) return } }
3:09 AM
いまいじったらこうなった
Avatar
なるほど
3:11 AM
guard 文もなかなか改行が難しいよな…
Avatar
2行以上の文のときは { を冒頭に持ってくる派
Avatar
最近は guard let a = a, let b = b, let c = c else { return } のようにしてます
3:12 AM
let 揃えるべきかなやむw
Avatar
悩ましいですね。 guard が 3 文字だったらよかったのに・・・。
3:19 AM
guard の後で改行とか?
Avatar
なんかそこまで行っちゃうともはや神経質なレベルなんじゃないかと思って()
Avatar
そんなあなたに guard let a = a , let b = b , let c = c else { print(2) return }
Avatar
guard let a = a , let b = b , let c = c else { print(2) return } これで完璧!w (edited)
Avatar
↓とかもできるし、 guard 後改行でもいい気が。 let a = 42 let b = 99 if a >= 0, a < 100, a != b { print(a) }
3:23 AM
惜しいのは、最後のa != b の後に , が書けないこと。
3:23 AM
↑の前カンマ、マジレスすると if let がダメ・・・。
Avatar
前カンマは割りとアリで、型パラのcondition書くのにも使ったりする
3:31 AM
class Foo<X, Y>: SuperFoo where X: Sequence , Y: Collection ... { ... }
3:31 AM
こんな感じ
Avatar
カンマ後ろでインデントはダメですか?
Avatar
前カンマの方がXcodeの破壊レベルが低かった気がする
Avatar
class Animal {} class Cat<X, Y> : Animal where X: Sequence, Y: Collection, X.Element == Y.Element {}
3:33 AM
↑オートインデント
Avatar
ありゃ、結構ちゃんとしてますね
Avatar
class Animal {} class Cat<X, Y> : Animal where X: Sequence, Y: Collection, X.Element == Y.Element {} where出すとこんな感じ
Avatar
guard 後改行いい気がしてきた。 let a: Int? = 2 let b: Int? = 3 guard case let a? = a, case let b? = b else { fatalError() } print(a + b) // 5
3:38 AM
初めて case let 複数書いた。
Avatar
実際そういうケースだとどっちがnilだったのか fatalErrorのメッセージとか、デバッガの停止位置でわかりやすいから、guard自体分けちゃう事が多い
3:39 AM
まとめて書いておくといざそこにヒットしたときに、さてどっちがコケたんだっけってなって面倒だ
Avatar
そもそもguard でfatalErrorはアンチパターンなので葉という気がしている
3:40 AM
それなら!使ったほうがマシ
Avatar
いや、今 fatalError
3:40 AM
別に return とかでもいいんですが
Avatar
でもfatalERrorのほうがメッセージが仕込めるよ
Avatar
optInt !! "xxxx" これがあればいいな
Avatar
ああ、そうだねw
3:41 AM
それは賛成。
Avatar
トップレベルだったのでそうしただけで意味はないです。
Avatar
何もしないで脱出する場合でも
3:42 AM
なぜか何も起こらない→バグで早期脱出に流れてそう
3:42 AM
っていうデバッグ作業は生じるので同じ気もするけど、メッセージとかは無いから処理は共通化したい度は高いな
Avatar
↑全部書いてあったw (edited)
Avatar
// の後の絵文字がイタリックになってるの超ウケるんだけどwwwww
😆 1
Avatar
// :thinking:
Avatar
絵文字のイタリックあるんだw
4:06 AM
↑の投稿で自分で書いたコードが↓になってた。 guard let a = ..., let b = ... else { ... } let sum = a + b
4:07 AM
まあ、発表(投稿)のためだから、コードがぱっと見でわかりやすいためにはこのインデントも仕方ないけど。 (edited)
Avatar
えー、↓これできないの? struct Foo<T> {} extension Foo where T == Int { typealias A = Int64 } extension Foo where T == Float { typealias A = Double }
Avatar
え、できないですっけ?
4:45 AM
typealiasのところ?
Avatar
error: repl.swift:8:15: error: invalid redeclaration of 'A' typealias A = Double ^ repl.swift:4:15: note: 'A' previously declared here typealias A = Int64 ^
Avatar
redeclarationだ
Avatar
Aをassociatedtypeにしてそれぞれのsubprotocol作って…となりそう
Avatar
最初のSwift 4.1スナップショットswift-4.1-DEVELOPMENT-SNAPSHOT-2017-10-25-aが出た (edited)
Avatar
@koher protocol FooParameterProtocol { associatedtype X } extension Int: FooParameterProtocol { typealias X = Int64 } extension Float: FooParameterProtocol { typealias X = Double } struct Foo<T: FooParameterProtocol> { typealias A = T.X }
Avatar
↑同じ事考えてた
Avatar
辛いww
5:30 AM
↑ができるのになんで元のはできないんだろう?
Avatar
typealias が定義できる場所が型ネームスペース的な場所になってしまっているんでしょうね
5:31 AM
extensionスコープにはなっていない
Avatar
それって Sema がそうなっているというだけで対応することに特に問題はない? (edited)
Avatar
む、もしかして別ファイルだと出来たりします? < extension毎typealias
Avatar
別ファイル・・・やってみます。
Avatar
それって Sema がそうなっているというだけで対応することに特に問題はない?
いや、後者の例だと、FooはどんなTでも T.A があることになっているけど
5:33 AM
前者の例ではあくまでIntとFloatの場合だけの話しで、 String のときに T.A があるかはかわらないから
5:34 AM
意味も違う話だと思う。
Avatar
違いがあるのはその通りだけど、できないのが意図的なのかがわからない
Avatar
そうですね。
Avatar
複数ファイルダメでした。 https://github.com/koher/experiment-alias-in-extension
Contribute to experiment-alias-in-extension development by creating an account on GitHub.
👍 1
Avatar
public struct Foo<T> {} extension Foo where T == Float { private typealias A = Double } extension Foo where T == Int { private typealias A = Int64 } private だと別ファイルと同ファイルで挙動がちがう。 これは SE-0169 の副作用っぽいです。 https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
private だと互いに不可視だからエラーにならなくていいんじゃないですか? (edited)
6:12 AM
可視のときにエラーになるのが意図的なのかがよくわからないです・・・。
Avatar
https://bugs.swift.org/browse/SR-5392 意図が違うかもだけど、一応似たようなイシューとしては登録されているみたいです。 (edited)
6:23 AM
(母体にも同名のtypealiasがあるパターンだから違う)
Avatar
ありがとうございます。ちょっと違うけど、これ考えるときについでに考えるかもしれませんね。
Avatar
Swift 4.1にはswift formatとか付いてるのね。 $ TOOLCHAINS=org.swift.4120171025a swift format --help 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.
👀 2
Avatar
マジ!
Avatar
Xcodeとはちょっと違うインデントになるぽい。
Avatar
それはどうなんだw
Avatar
ゴゴゴ
9:45 AM
Xcodeがそれ参照してくれるのが平和への道
Avatar
だね
Avatar
Xcode も iOS も SwiftPM の世界では二級市民だから・・・( iOS は三級か?)
Avatar
これXcodeのBuildScriptに差し込んで
9:47 AM
無限にformat直させ合うか
Avatar
Xcodeつかうのやめたほうがかしこそう
Avatar
#if swiftとかで条件が外れる箇所のインデントが崩れるのはXcodeと同じみたいだから、常用するのは難しそう。
9:50 AM
#ifでインデントが深くならないのがXcodeとの最大の違いかな。 (edited)
Avatar
xcodeでも
Avatar
クロージャ式の閉じ } が気になる
Avatar
importはインデント深くなるけど
9:51 AM
classの中のfuncとかはインデント変わらないような気がする
9:51 AM
#if os(iOS) import UIKit #endif class Cat { #if os(iOS) func nya() { } #endif }
9:51 AM
//xcodeだとこうなる↑
Avatar
#if os(iOS) import UIKit #endif class Cat { #if os(iOS) func nya() { } #endif } (edited)
9:54 AM
行をまたいだフォーマットはしないぽい。
9:55 AM
まあ、気になる人はスナップショットswift-4.1-DEVELOPMENT-SNAPSHOT-2017-10-25-a出てるから試して。 (edited)
Avatar
7種類の@conventionのうち、.swiftで使えるのは3種類だけでした。 let thin: @convention(thin) () -> Int = { 1 } //let thick: @convention(thick) () -> Int = { 1 } // error: convention 'thick' not supported let block: @convention(block) () -> Int = { 1 } let c: @convention(c) () -> Int = { 1 } //let objc_method: @convention(objc_method) () -> Int = { 1 } // error: convention 'objc_method' not supported //let method: @convention(method) () -> Int = { 1 } // error: convention 'method' not supported //let witness_method: @convention(witness_method) () -> Int = { 1 } // error: convention 'witness_method' not supported
📍 1
Avatar
使えるというか
2:48 AM
methodとかは cat1.eat
2:48 AM
とかで取り出せるんじゃないですかね?
2:48 AM
ラムダ式に明示する形で生成できるかっていう視点だと条件が変わってしまっていると思う。
Avatar
そうですね。
Avatar
結局取り出そうとしたらまさかのコンパイラが死んだか・・・
Avatar
レポートがめちゃシンプルで良い・・・
Avatar
ちなみにfuncdumpするとシンボルとか見られる 1> struct S { func f() {} } 2> dump(S.f) - (Function) $R0: (S) -> () -> () = 0x00000001000fca30 $__lldb_expr4`partial apply forwarder for reabstraction thunk helper from @escaping @callee_owned (@in __lldb_expr_1.S) -> (@out @escaping @callee_owned (@in ()) -> (@out ())) to @escaping @callee_owned (@unowned __lldb_expr_1.S) -> (@owned @escaping @callee_owned () -> ()) at repl3-18ad44..swift
Avatar
ほー
Avatar
こんな古くからあるバグだったとは… https://bugs.swift.org/browse/SR-75 (edited)
Avatar
そもそも P.method(object) みたいなのも出来ないですよね
Avatar
oh duplicateついてた
3:47 AM
JIRAって「ウォッチしてる課題一覧」ってどこで見れるんですか?
Avatar
このクエリは複雑すぎるためベーシックモードでは表示できません・・・
Avatar
ぬぬ
Avatar
ああいや、表示自体はできていますが
3:50 AM
アドバンスモードでこのクエリーを手打ちするしかないってことでいいですか?
3:51 AM
norioさんはいまこの watcher = currentUser() ORDER BY updatedDate DESC を手打ちしたんですか? それともどこかにリンクある?
Avatar
⭐ つけるとFAVORITE FILTERSに載ってくる
Avatar
お。
Avatar
filter自体はPopular Filters https://bugs.swift.org/secure/ManageFilters.jspa?filterView=popular で見つけた (edited)
Avatar
なるほど。
3:52 AM
ありがとうございます、とりあえずこれで自分は助かります。
3:52 AM
そこにあって人気ってことは、基本的に一度はカスタムで作るのか・・・すごい不便なウェブアプリだなあ
Avatar
https://twitter.com/slava_pestov/status/923752360299528192 古ーいバグはもはや仕様と割り切れと。😬
@griotspeak It should say “fixing long standing bugs in the compiler is not a priority; enjoy these new features instead
😨 1
📍 1
Avatar
ひどいw
Avatar
ちょっと意味違うかw
Avatar
ツイッター上でめっちゃ話続いてるなあ
Avatar

Type erasure

swift では protocol を使うのが人気です。ある protocol を満たす複数の型があるとき、それらのどれでも代入できる互換性のある型が欲しくなることがあります。そのような型を type ...
😀 1
👍 1
📍 1
8:12 AM
この前の話題の件をまとめました
8:12 AM
この記事の内容は Discordのみなさん と、特に @rintaro#5593 に教わりました。ありがとうございました。 (edited)
8:12 AM
謝辞も書きました。
Avatar
最終的に全部 class にしているのは、クロージャ方式が大きくなりすぎるから?
Avatar
それもひとつです。 structだとそれ自体が強参照ポインタのように振る舞うので、weakで使いたい場合を考えると面倒なのと、 structだとprotocolのmutating指定も絡んで複雑になるのでシンプルにしたかった。
Avatar
なるほど。
Avatar
class だと「シンプルプロトコル」で existential でないといけない理由がわかりづらいような・・・
📍 1
8:47 AM
Java の interfaceclass のノリで考えてしまいそう。
Avatar
でないといけない、とは?
8:50 AM
シンプルプロトコルの場合は載せてる方式の3つのどれでもいけますよ
Avatar
Java のノリだと interface は型でただの interface 型の変数はただのポインタだから、一番最初の説明で AnimalProtocolCat 入れるの見て、前知識がない人だと existential って何? interface と違うの?ってなりそう。
8:52 AM
struct だとそのまま抽象的に扱えないから interface との違いに気付くきっかけがある。
Avatar
こんなことしないでclass Animalでええやん、って話か。
Avatar
// Java interface Animal {} class Cat implements Animal {} Animal animal = Cat(); ↑と同じように見えてしまうってこと。 (edited)
Avatar
そのレベルの人にTEの必要性や利便性を説得することは目的としていなくて、 実装しようとして困った人にむけてた(過去の自分
8:56 AM
2つ前のトライSwiftでエニーポケモンがさんざんバズったし、、、
8:56 AM
もうそこはいいかなって。
Avatar
他の言語には習熟してるけどこれから Swift を始める人とかは?
8:59 AM
いやまあ、どこで線を引くか次第だからそれでもいいんだけど、これだと Swift プログラマの数%(ここに参加してる人が母数なら数十 % になるだろうけど)以外は最初でコケちゃいそうだなぁと。
8:59 AM
まあ、 struct にすることで気付きが得られるのもわずかかもしれないけど・・・
Avatar
最近 @hiragram と話してて指摘されたんだけど
Avatar
はい
Avatar
初心者 is 何問題か
Avatar
そもそも「他の言語は習得してるけどswiftは初心者」
9:00 AM
っていう初心者像自体かなりバイアスだって
9:00 AM
話があって
9:01 AM
「まともにやり始めたのがswift、Javaとかしらん」っていう (edited)
9:01 AM
人がたくさんいると思うって話もあり・・・
🙋 1
9:03 AM
Javaの常識からSwiftのモダンパラダイムへ って論の流れだと逆にハードルが上がって余計わからなくなる説がある
Avatar
func spawn() -> Self { return type(of: self).init() } これ return Cat() じゃダメなんだっけ?
Avatar
final class Catならそれでオーケー
9:06 AM
もしくはstruct
Avatar
ああ、なるほど。
9:07 AM
だから required なのか。
Avatar
classだとrequired initと合わせてそうなる
9:07 AM
もしくはreturn selfでもいいけどspawnの例としては変なのでそうなった
Avatar
あれ? Self.init() ってダメだったっけ?
Avatar
あ、それは試してないです。後で試してみます。
Avatar
TempGround.playground:8:16: note: did you mean 'self'? return Self.init() ^~~~ self
Avatar
そか、protocol extension内でしか使えないか。
🙂 1
Avatar
MLにスタッククラスという機能の話題が出てて、 それって moveonly struct じゃダメなんかな、と思いつつ眺めてたら、 John McCall がそう返信してた。
Move-only struct types will be able to provide deinit. See the ownership manifesto.
👍 1
📍 1
2:01 AM
[swift-evolution] [Discussion] Swift for Data Science / ML / Big Data analytics ラトナの返信
In short, I think we should build a simple Swift/Python interop story.
let np = Python.import(“numpy”) // Returns a value of type Python.Object. let a = np.array([1, 2, 3]) print(type(a)) // Whether we want to support type(x) or use the Swift equivalent would be up for discussion of course! print(a.shape) print(a[0], a[1], a[2]) a[0] = 5 print(a) let b = np.array([[1,2,3],[4,5,6]]) print(b.shape) print(b[0, 0], b[0, 1], b[1, 0])
Avatar
Swift の += 等の左オペランドが inout だけど & が要らないのってなんでなんですっけ?演算子の場合は & 不要? (edited)
Avatar
var a = 1 a += 1 (+=)(&a, 1)
8:47 AM
演算子で省略してくれるんじゃ
Avatar
左オペランドのみ?
Avatar
のみとは?
Avatar
右オペランドが inout だとどうなるんだろう?
Avatar
Kishikawa Katsumi 10/30/2017 8:48 AM
なぜ多くの開発者が今なお Swift よりも Objective-C を好むのか  の記事を読んだ。 私は、言語にあまりこだわりがある方ではなく、使えればなんでもいいやタイプ。 そんな私でさえ、「あー、そうよなー」 と共感してしまった所があった。 WWDCのセッションで...
8:48 AM
今後、Swiftライブラリをアプリに含めなくても良くなる (= Objective-Cと同等レベルの言語として格上げされる) 予定があるのか? ないのか? をホント、知りたい。
公表してくれると嬉しいが、オトナの事情もあるだろうし難しいんだろうな....。
Avatar
これは予定はあるんじゃないですか?
Avatar
Kishikawa Katsumi 10/30/2017 8:49 AM
^ ABIが安定してしばらく経ったら必要なくなるよと教えてあげたいけど、コメント書けないっぽいし、コンタクト先もわからない。
Avatar
ABI安定化すれば。
Avatar
Kishikawa Katsumi 10/30/2017 8:49 AM
誰か知ってる人いないかなー、っていう。
Avatar
infix operator +=+ func +=+(lhs: Int, rhs: inout Int) { rhs += lhs } 1 +=+ a
Avatar
Swift の += 等の左オペランドが inout だけど & が要らないのってなんでなんですっけ?演算子の場合は & 不要?(編集済)
そう
Avatar
@t.ae おお。
Avatar
もしそこが厳格なら通常の代入文も・・・
Avatar
Kishikawa Katsumi 10/30/2017 8:50 AM
あ、flaskappの人か。じゃあ知り合いがいた。
Avatar
右がinoutってできるんだ
Avatar
@omochimetaru いや、そうなんだけど、どこかに名言されてたかなぁ?とふと思って。
Avatar
じゃあ += にかぎらず一般のオペレーターで inout 自動付与か
Avatar
オペランドの右左も関係なさそうだね。
8:51 AM
演算子でラベルがいらないのと同じ特別扱いか。
Avatar
両方inoutでも両方省略できました。
8:52 AM
ユースケースが思いつかない
Avatar
ラベルも付けれない。 1> infix operator +- 2. func +-(lhs: Int, rhs: Int) -> Int { 3. return lhs + rhs - 1 4. } 5> (+-)(2, 5) $R0: Int = 6 6> (+-)(lhs: 2, rhs: 5)
8:54 AM
1> infix operator +- 2. func +-(lhs lhs: Int, rhs rhs: Int) -> Int { 3. return lhs + rhs - 1 4. } error: repl.swift:2:9: error: operator cannot have keyword arguments func +-(lhs lhs: Int, rhs rhs: Int) -> Int { ^~~~ error: repl.swift:2:23: error: operator cannot have keyword arguments func +-(lhs lhs: Int, rhs rhs: Int) -> Int { ^~~~
8:57 AM
@Kishikawa Katsumi 見つけました。 https://twitter.com/aqubi
IOS App Developer. co-founder of http://flaskapp.com/. I love gadget, rabbit, making new things.
Tweets
12356
Followers
1087
Avatar
Kishikawa Katsumi 10/30/2017 8:58 AM
@koher すばらしい。ありがとうございます。
🙂 1
Avatar
ABIの安定化ってそんなに難しいのかな 全然中身を知らないからわからない
Avatar
基本的にはヒープ上の関数呼び出しのときの型のメモリレイアウト、例外仕様とかですね
📍 1
1:37 AM
最適化したときの挙動と、モジュール跨いでも安全な冗長な挙動 あとはasyncとかオーナーシップとか、 言語本体機能が定まらないと、 それのABIも決まらないから
1:38 AM
「この機能はABIに影響与えるから早く話し合いたい」ってだいたいの提案に書いてありますよ・・・
Avatar
なるほど
1:38 AM
まだその辺のベースが定まらないってことなのか
1:39 AM
定めちゃうと変更できなくなるし
Avatar
そうですね。 やることリストはこれ https://github.com/apple/swift/blob/master/docs/ABIStabilityManifesto.md
swift - The Swift Programming Language
Avatar
Currently only single 'inout' flag has been encoded into function metadata, these changes extend function metadata to support up to 32 flags per parameter.
2:01 AM
↑関数型のmetadata(多分metatypeのこと?)の改善PRとかWIPだし多分これもABI周り
2:02 AM
Conditional conformanceとかもあるか。その条件付きwitness tableをシリアライズしないといかんし
Avatar
ABI stabilityの状況はこっちの方がわかりやすい? https://swift.org/abi-stability/
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
お、これは良いですね。前見たけど忘れてた。
Avatar
Any型の値があるときに、それがclass型なのか値型なのか判別する方法
8:47 AM
class Cat {} struct Dog {} let cat = Cat() let dog = Dog() func checkIsClassValue(_ arg: Any) -> Bool { return (arg as AnyObject) === (arg as AnyObject) } checkIsClassValue(cat) // true checkIsClassValue(dog) // false こういうの考えてるんですが、もうちょっと効率いい方法無いですかね
8:47 AM
Mirror使えばいけるかな。
8:51 AM
func checkIsClassValue(_ arg: Any) -> Bool { return Mirror(reflecting: arg).displayStyle == .some(.class) } こっちのほうが上品っぽい
📍 1
Avatar
Kishikawa Katsumi 10/31/2017 8:54 AM
後者の方が良さそうですね。前者は checkIsClassValue(1)true 。たぶんFoundationのせい。
Avatar
ゲゲーッ
8:54 AM
ありがとうございます
8:54 AM
やば
Avatar
public func castIfClass(_ x: Any) -> AnyObject? { guard type(of: x) is AnyObject.Type else { return nil } return x as AnyObject }
Avatar
良さそう
9:04 AM
値だとautoboxing走って困ってた、型ならboxingされない、は確かに
Avatar
そうそう。
Avatar
一つだけ気になるのはこの関数はutilなんでinternalかな
Avatar
まあそこはご自由に・・・
Avatar
Kishikawa Katsumi 10/31/2017 9:12 AM
func checkIsClassValue(_ arg: Any) -> Bool { return type(of: arg) is AnyClass }
📍 1
Avatar
AnyClassはAnyObject.Typeのエイリアスですね
Avatar
Kishikawa Katsumi 10/31/2017 9:13 AM
ほんとだ public typealias AnyClass = Swift.AnyObject.Type
Avatar
なるほど。エイリアスがせっかくついてるしそっちのほうがオシャレだな
Avatar
面白いのみつけた
11:23 AM
let a: @convention(block) () -> Int = { 42 } type(of: a) // @conversion(block) () -> Int (a as AnyObject) === (a as AnyObject) // true let b: Any = a type(of: b) // @conversion(block) () -> Int (b as AnyObject) === (b as AnyObject) // false
📍 1
11:23 AM
型は変わってないけど as AnyObjectの挙動が変わる
Avatar
Anyにするときにboxingされとるのかな?
Avatar
Any boxingありそう
2:07 PM
Optionalのキャスト周りで2から3の時も似たようなのがあった気がする
2:09 PM
あー
2:10 PM
Anyでboxingが発生してるのではなく、キャスト前の型によってasがオーバーロードしてる方がありそう?
2:10 PM
中間コード見るのがはやそう
Avatar
dump ConventionAnyObjectExample.swift
2:39 PM
見る場所合ってるか怪しいけどこの辺り? (var_decl "a" type='@convention(block) () -> Int' interface type='@convention(block) () -> Int' access=internal let storage_kind=stored) (var_decl "b" type='Any' interface type='Any' access=internal let storage_kind=stored)
3:30 PM
これかなー
3:32 PM
ここのisClassOrObjCExistentialがGenericsParameterからT.selfと取っているので、
📍 1
3:32 PM
コンパイル時の型で判定だね
3:32 PM
@convention(block) () -> Intなら(@convention(block) () -> Int).selfと同値だし、
3:32 PM
Anyになっていると、Any.Protocolになります。
3:33 PM
バグならprチャンス?
Avatar
なるほど、ここで型変数から受け取ったkindで比較してるからコンパイル時の型になるわけですね https://github.com/apple/swift/blob/bcb9571079cd86cbd6e7baa68e7e414460532a8f/stdlib/public/runtime/Casting.cpp#L2632-L2651
swift - The Swift Programming Language
Avatar
func typeOfCompileTime<T>(_ x: T) -> Any.Type { return T.self } これで確認できますね
Avatar
ふむふむ import Foundation func typeOfCompileTime<T>(_ x: T) -> Any.Type { return T.self } let a: NSNumber = 1 typeOfCompileTime(a) // __ObjC.NSNumber.Type let anyA: Any = a typeOfCompileTime(anyA) // -> Any.Protocol (edited)
3:46 PM
ここを見るとvalueも取ってそうなのに、Tだけしか見てないのは何か意図がありそう? https://github.com/apple/swift/blob/bcb9571079cd86cbd6e7baa68e7e414460532a8f/stdlib/public/runtime/Casting.cpp#L3190
swift - The Swift Programming Language
Avatar
omochimetaru 11/1/2017 1:22 AM
let a: @convention(block) () -> Int = { 42 } print("a") dump(a) print() type(of: a) // @conversion(block) () -> Int (a as AnyObject) === (a as AnyObject) // true print("a as AnyObject") print(type(of: a as AnyObject)) dump(a as AnyObject) print() let b: Any = a print("b") dump(b) type(of: b) // @conversion(block) () -> Int print() (b as AnyObject) === (b as AnyObject) // false print("b as AnyObject") print(type(of: b as AnyObject)) dump(b as AnyObject) print()
1:22 AM
a - (Function) a as AnyObject __NSMallocBlock__ - <__NSMallocBlock__: 0x608000243390> #0 - super: __NSMallocBlock - super: NSBlock - super: NSObject b - (Function) b as AnyObject _SwiftValue - (Function) #0 - super: NSObject
1:25 AM
Any経由からAnyObjectにするところで、 _SwiftValue にboxingされてるのが原因?
1:25 AM
a as AnyObject の結果は NSMallocBlock だから、ラップはされてない感じだね
Avatar
多分、SwiftValueが発生するのが、
2:05 AM
_bridgeAnythingNonVerbatimToObjectiveCの中ではという気がしている
Avatar
omochimetaru 11/1/2017 2:06 AM
それはグローバル関数?
2:07 AM
xcodeでブレークポイントをシンボル指定で貼ればわかるかな
2:08 AM
この辺、議論はちょい上
Avatar
omochimetaru 11/1/2017 2:11 AM
NSMallocBlock は関係なくて、シンプルに Any から AnyObjectへのキャストの話で、 ObjCブリッジ関係は関係ない気がする
Avatar
dumpすると_bridgeAnythingToObjectiveCっていうのが出てくるよ。 (edited)
2:14 AM
で、これがどうも型パラとって動いてるから切り替わるならこの中か、@_inlinableとかやってそうだなと思ったので掘り下げた
Avatar
omochimetaru 11/1/2017 2:15 AM
これって -dump-ast?
📍 1
Avatar
そうだと思う。僕も-dump-astで似たような結果は確認した。
Avatar
omochimetaru 11/1/2017 2:18 AM
たしかに。 let c: AnyObject = 3 as AnyObject これだけで、 (declref_expr implicit type='(Int) -> AnyObject' decl=Swift.(file)._bridgeAnythingToObjectiveC [with Int] function_ref=single) がでてきた。
2:18 AM
import Foundationなくてもそうだ。
2:19 AM
ASTの時点でこんな書き下されてるの違和感あるな
2:21 AM
てことはAnyObjectって結構内部では ObjectiveCオブジェクトって概念なのか?
Avatar
これちゃうかな
Avatar
omochimetaru 11/1/2017 2:25 AM
めっちゃこれっぽい
Avatar
てっきりimport Foundationしたらこれにすげ変わるのかと思ってたけどしなくてもこいつなのか
Avatar
omochimetaru 11/1/2017 2:25 AM
すでにObjCオブジェクトなのに自分で isaメンバ書いてる・・・
Avatar
因みに
Avatar
omochimetaru 11/1/2017 2:25 AM
#if __has_attribute(objc_root_class) __attribute__((__objc_root_class__)) #endif SWIFT_RUNTIME_EXPORT @interface SwiftObject<NSObject> { @private Class isa; SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS; }
2:26 AM
objc_root_classってのをつけると、標準生成のisaとかが消えて、手書きできるんかな・・・
2:26 AM
もしかして、Linux版だと、さっきの、 _bridgeAnythingToObjectiveC が出てこなかったりする?
Avatar
import Foundation class Cat{} (Cat() as AnyObject).superclass でこいつにたどり着く
Avatar
omochimetaru 11/1/2017 2:27 AM
__ObjC.SwiftObject.Type
2:28 AM
え、その superclassなに
2:28 AM
import foundationしたら出て来るのか
Avatar
import FoundationしたらAnyObjectがNSObject互換になるマジック
Avatar
omochimetaru 11/1/2017 2:30 AM
でもObjCランタイム環境では、import Foundationが無くてもObjCオブジェクトではあるっぽいね
2:30 AM
NSObjectはFoundationからくるけど
Avatar
import Fondationしないとこの辺のメソッド参照できないっぽいんだよね
Avatar
omochimetaru 11/1/2017 2:31 AM
うむ
Avatar
これはズルなので、やめようね!という提案が最近evolutionに上がってた
Avatar
omochimetaru 11/1/2017 2:31 AM
あーあったね
2:32 AM
なんかもっとAnyObjectをきれいにしようみたいなやつ
Avatar
そうそう
Avatar
norio_nomura 11/1/2017 2:38 AM
綺麗なAnyObject
Avatar
"きこりの泉"が必要だ
Avatar
きこりの泉があったら Optionalisas も Variance も入れなきゃいけないものが多すぎる・・・
😂 1
Avatar
omochimetaru 11/1/2017 2:51 AM
きこりの泉 「きれいな○○」製造機。女神さまも大変。
Avatar
Mirror使ってsuperclassの型取れませんでしたっけ
Avatar
きこりの泉だと汚いものも一緒に返ってくるか一切無くなるかの二択なのでは
Avatar
struct S {} class C {} S.self is AnyObject // false C.self is AnyObject // true この挙動を初めて知ったという雑ネタ
Avatar
omochimetaru 11/1/2017 8:50 AM
意外です (りんたろさんが知らなかったのは (edited)
Avatar
asで通ればis trueと思ったら例外いっぱいある
Avatar
omochimetaru 11/1/2017 8:51 AM
え、マジ? as と is は揃ってると思ってた
Avatar
あれ
8:52 AM
あ、上のはas通らないやつか
8:52 AM
functionどうなってたっけなと思ったら通った
8:53 AM
func x() -> Int { return 0 } x as AnyObject x is AnyObject
Avatar
S.self as AnyObject === S.self as AnyObject // false っていうね。 (edited)
Avatar
これですらtrueなんですね
8:53 AM
これはboxingですね (edited)
Avatar
omochimetaru 11/1/2017 8:54 AM
ですねですね
8:54 AM
ん?
8:54 AM
あ、 .self
8:55 AM
S.self はメタタイプだから最初からヒープオブジェクトかと思いきや
8:55 AM
メタタイプも値的にboxingされるのか?
📍 1
Avatar
よく考えたら明示してたらautoではない
Avatar
これなんでなの? S.self is AnyObject // false
8:58 AM
なんでというのは、何のため?
Avatar
スタティックに存在するはずだから、 reference タイプで問題ないはずっていう疑問ですよね?
Avatar
omochimetaru 11/1/2017 8:59 AM
僕もそう思いました。
Avatar
はい。
9:00 AM
C.selfAnyObject なのに S.selfAnyObject であってほしくない理由がよくわからないです・・・。
9:00 AM
両方とも AnyObject でないならまだわからんでもないけど。
Avatar
S.selfがどうやってもObjective-C側から観測不可能だから?
Avatar
omochimetaru 11/1/2017 9:01 AM
struct S {} S.self === S.self // Binary operator '===' cannot be applied to two 'S.Type' operands
Avatar
AnyObject は ObjC と不可分なんですっけ?
Avatar
ObjC の Class タイプと互換性とるためか?
Avatar
純粋な Swift 的には( Linux では)関係がない話な気も?
9:03 AM
!!!
9:03 AM
↓ Ubuntu 上で。 $ swift Welcome to Swift version 4.0 (swift-4.0-RELEASE). Type :help for assistance. 1> struct S {} 2> S.self is AnyObject $R0: Bool = false 3> class C {} 4> C.self is AnyObject $R1: Bool = false
Avatar
うは!
Avatar
omochimetaru 11/1/2017 9:03 AM
かわるんか〜〜〜い
Avatar
ww
Avatar
何か自分が間違えてないか疑いたくなるレベルw
Avatar
Xcode9.1でSwift4.0.2が入ったんですが、
12:02 PM
ここからString.charactersがdeprecatedですかね?
Avatar
4.0からdeprecatedにはなってなかった・・・?
Avatar
4.0なってましたっけ
12:05 PM
SwiftProtobufが.charactersつかってるのと警告をコンパイルエラーにするコンボが入っていて
12:05 PM
CarthageでSwiftProtobufを4.0.2でビルドするときだけ失敗するという状態になっている
📍 1
Avatar
4.0.2対応ブランチとかないんですか
Avatar
リリースしか見てなかったらからワンちゃん
🐕 1
12:06 PM
なかったです
👼 1
12:08 PM
これは普通にPR投げるのがかしこいな
Avatar
protobuf使うような人たちならbeta追いかけて対応してそうなもんなのにね
12:09 PM
マスターでビルドコケて草
12:09 PM
なおしますね
12:11 PM
/// A view of the string's contents as a collection of characters. @available(swift, deprecated: 3.2, message: "Please use String or Substring directly") public var characters: String.CharacterView あれ?3.2からだっけ…
Avatar
ww
Avatar
Xcode 9.1 betaでwarningが出る様になりましたね。
Avatar
Xcodeで変わったってことはSwift側じゃなくてstdlib側か。。。
📍 1
Avatar
QiitaのAdvent Calendar出遅れてもうSwiftカレンダー埋まっちゃった 😇
Avatar
omochimetaru 11/2/2017 1:48 AM
一瞬だった
Avatar
すぐ埋まりましたね。 Swift2を作ってもいいかも?
1:49 AM
↓みたいな感じで。 https://qiita.com/advent-calendar/2017/go2
Goのアドベントカレンダー(その2)です! 登録後にキャンセルされる場合、書く予定だったが書けなくなった、などは Twitter で @mattn_jp にご連絡下さい。 予定日を過ぎても投稿がない場合、お伝えする事なく他の方にエントリして頂きます。ご了承ください。 [その1](https://qiita.com/advent-calen...
1:49 AM
Swift4が出ましたが、このカレンダーのURLはswift2です( ´・‿・`) どうぞご自由にSwiftに関して投稿ください
1:49 AM
すでにあった。
1:49 AM
ってか @lovee さんも登録済みだった。
Avatar
はい、とりあえず登録しておいてからここに書き込みましたw
Avatar
なるほどw
1:51 AM
Goがすでに3になっててすごい https://qiita.com/advent-calendar/2017/go3
Goのアドベントカレンダー(その3)です! 登録後にキャンセルされる場合、書く予定だったが書けなくなった、などは Twitter で @mattn_jp にご連絡下さい。 予定日を過ぎても投稿がない場合、お伝えする事なく他の方にエントリして頂きます。ご了承ください。 [その1](https://qiita.com/advent-calen...
1:52 AM
@mono その2にリンクしてあげるといいかもです。埋まってた人のための導線として。 https://qiita.com/advent-calendar/2017/swift
Taylorじゃない方のSwiftです( ´・‿・`) ---
Avatar
余談ですがAdventarにも結構いろんな面白いAdvent Calendarがあって面白い(語彙力皆無 https://adventar.org
1:57 AM
これとかねw
1:57 AM
退職者 Advent Calendar 2017
Avatar
あ、退職者カレンダーにすでに登録済みです()
😇 1
Avatar
毎年、色々なジャンルのAdvent Calenderを見るのが楽しみなのですが、投稿者選抜ってジャンルによってはこんなに壮絶だったのですね。
Avatar
omochimetaru 11/2/2017 3:02 AM
FD_SET などのC言語マクロが Swift から呼び出せないからそれをブリッジするだけのObjectiveCソースを追加する必要があって残念
4:15 AM
Array.removeFirst、最初の要素をreturnしつつ削除してくれるんだけど
4:15 AM
Optionalになってなくて空だとクラッシュなのが
4:15 AM
.first との対応として違和感がある
Avatar
1個目の取得と1個目の削除っていう2つの機能が1個になってる感じがしてきもちわるめなので使わないようにしてるから気づかなかった。
Avatar
omochimetaru 11/2/2017 4:39 AM
わりとよくやるのが while let first = array.first { someCleanup(first) array.removeFirst() }
4:40 AM
こうやって先頭から一個ずつ片付けるときとかで、
4:40 AM
while let first = array.removeFirst() { someCleanup(first) }
Avatar
arrayからは消したいのね
Avatar
omochimetaru 11/2/2017 4:40 AM
こう書けたら良かったのになあ。ってなる。
4:40 AM
うん。
Avatar
それってforEachぶん回したあと空配列代入するじゃだめなの
Avatar
omochimetaru 11/2/2017 4:41 AM
someCleanupの内部でこの配列に要素が増えたりする可能性がある
Avatar
ゲー
4:42 AM
🤔
Avatar
オレオレremoveFirst作ってoverloadしたら
Avatar
omochimetaru 11/2/2017 4:42 AM
まあこのパターン自体はどうとでも道具は作れるからいいんだけど removeFirst の API は変じゃないかって話
Avatar
forEachの途中で要素増えたらどうなるんだろう
Avatar
if let のときはOptionalが優先される気がする
Avatar
omochimetaru 11/2/2017 4:43 AM
for - in 中の変更って許されてたっけな
Avatar
forEachの中で要素増えてもそのforEachには影響なかった
4:47 AM
増える前の配列でforEach終わった
Avatar
omochimetaru 11/2/2017 4:47 AM
それはforEachメソッド?
Avatar
class Hoge { var array = [0,1,2,3,4,5,6,7,8,9] func fuga() { array.forEach { [weak self] in print($0) self?.array.append($0 * 10) } } } let hoge = Hoge.init() hoge.fuga()
4:47 AM
0 1 2 3 4 5 6 7 8 9
Avatar
structのmutatingはコピーと同義じゃないの
Avatar
omochimetaru 11/2/2017 4:49 AM
func fuga() { for e in array { print(e) array.append(e * 10) } }
4:49 AM
これも同じ挙動やな
Avatar
つまりarray.forEachしたときのarrayとappendされたarrayは別物になるはず
Avatar
んだ
4:49 AM
コピーだべさ
Avatar
omochimetaru 11/2/2017 4:50 AM
そこ ownership で変わる可能性あって
4:51 AM
現状の実装だとイテレーターがコピーしてる(COWだから実コピーはされない可能性が高いけど)
4:51 AM
んだけど
4:51 AM
for shared employee in company.employees { if !employee.respected { throw CatastrophicHRFailure() } }
4:51 AM
shared イテレーション になると、コピーしないで直接参照できるようになる
📍 1
Avatar
したらループの中で毎回appendしてたら終わらんくなるの? (edited)
Avatar
omochimetaru 11/2/2017 4:52 AM
いや、それで、sharedイテレーションのレシーバ(Collection)は、for - in の呼び出しが nonmutating func の呼び出し期間扱いになるので
4:52 AM
読み込み参照として保護されていて
Avatar
コンパイルエラーにできるのか (edited)
Avatar
omochimetaru 11/2/2017 4:53 AM
appendしようとすると書き込み参照と衝突して落ちる(か、静的エラー)
Avatar
素晴らしい
Avatar
omochimetaru 11/2/2017 4:53 AM
だから、禁止されるってことだね
Avatar
ほっほー
Avatar
omochimetaru 11/2/2017 4:53 AM
Collectionに対するshared iterationはデフォルト挙動になって、普通の for in がそうなる
4:53 AM
Programs can explicitly request an iteration over a copy of the value in that storage by using the copy intrinsic function on the operand.
従来挙動は明示的に for x in copy(array) { ... } コピーしましょうねとか書いてある
(edited)
4:54 AM
で、もしそれが実装された場合
4:54 AM
mutating generator iterateMutable() -> inout Element { var i = startIndex, e = endIndex while i != e { yield &self[i] self.formIndex(after: &i) } } イテレーションされている間の処理を記述するメソッドが コルーチンになって yield が必要だよね という話が出てくる
Avatar
func copy<T>(_ arg: T) -> T { return arg }
Avatar
omochimetaru 11/2/2017 4:55 AM
(これまでの makeIterator() と next() との整合性はよくわからん・・・
4:55 AM
copy copy is a top-level function in the Swift standard library: func copy<T>(_ value: T) -> T { return value } せやな
4:56 AM
move The Swift optimizer will generally try to move values around instead of copying them, but it can be useful to force its hand. For this reason, we propose the move function. Conceptually, move is simply a top-level function in the Swift standard library: func move<T>(_ value: T) -> T { return value }
4:56 AM
move はコンパイラマジックになるので↑うさんくさいことに
4:57 AM
とまあ、そういう将来の話があるので、現状の for in 中の変更についての挙動は単なるツナギというかなんというか。
Avatar
胡散臭すぎて笑うw
Avatar
話戻るけど、 removeFirst は前からおかしいと思ってた。 Optional 返すべき。
Avatar
omochimetaru 11/2/2017 5:09 AM
5:10 AM
一応 removeAt(0) が空ならクラッシュする方に合わせてるんだとは思うんですけどね
Avatar
もしかすると popFirst が必要なだけかも。 (edited)
5:10 AM
これの先頭版がほしくなる。
Avatar
omochimetaru 11/2/2017 5:11 AM
そんなのあったのか
5:11 AM
なんでlastだけあるんだw
Avatar
いや
Avatar
popFirst は O(n) になるから?
Avatar
返すべき値が無いという意味なら返り値はOptionalが良いと思うけど、無いのにremoveはやっぱりクラッシュしたほうがいいんじゃないかという気持ちがあるんですが
Avatar
removeAt(0)はsubscript(0)との対なのでクラッシュはわかるけど (edited)
5:11 AM
removeFirstが落ちるのはやっぱりおかしい
Avatar
omochimetaru 11/2/2017 5:11 AM
別にええやんけ removeFirstもO(n) だし
Avatar
remove は落ちるのがいいと思うけど
Avatar
omochimetaru 11/2/2017 5:12 AM
なるほどね remove: 落ちそう + first: 落ちなそう
Avatar
removeFirst は実質的にほしいのは popFirst であるケースが多くて
5:12 AM
今の removeFirstremoveLast はいらない。
5:14 AM
まあ、 removeLastpopLastOptional に包むオーバーヘッドを避けるためにあるというのはまだわからんでもないけど、 removeFirst は意味不明。
5:15 AM
removeFirst は O(n) のはずだし、それと比べたら Optional に包むオーバーヘッドなんて微々たるものだからほしいのは popFirst だ。
5:15 AM
ただ、そうすると Array をキューとして使い出す人が出て来るから
5:15 AM
そのために popFirst を封じてるんだったらまだわかる。
5:15 AM
でもそれなら removeFirst もいらないと思う。
5:16 AM
ArraySlice なら O(1) だから、 ArraySlicepopFirst があれば良い?
5:16 AM
あった
Avatar
struct Queue: Sequence がstdlibにいればArrayをQueue代わりに使うみたいなのは封じれるんじゃ
Avatar
やっぱそういう意図で Array では封じられてるのか?
5:17 AM
なので、一度 ArraySlice に入れれば良さそう。
5:18 AM
var slice = array while let first = slice.popFirst() { someCleanup(first) }
5:18 AM
someCleanupslice をキャプチャできないか。
5:18 AM
まあ、最初から slice でもっておけば OK 。
5:20 AM
@tarunon Queue を入れると Stack も、ってなるし、どこで線引きするか難しい気がするんですよね。 Deque もほしくなるし。
Avatar
というかQueueとStack、structよりclassの方が効率良いなという気がしてきた
Avatar
stackのfirstとlastがどっちなのかってめちゃ混乱しそう
Avatar
mutable前提の構造だし (edited)
Avatar
@hiragram 後ろのイメージだけど Java の push, pop は先頭で操作してた気が。
Avatar
(First/Last) in (First/Last) out な組み合わせが
5:21 AM
5:22 AM
First in (First/Last) outか
5:23 AM
@tarunon それややこしいww FIFO キューは Last に要素を Insert すると。 First-in だけどw
Avatar
StackがSequenceになったときdropFirstしたらどこがドロップされるのかみたいな
Avatar
キューの前後と時刻の前後・・・
Avatar
ややこくなってきた
Avatar
というか厳密にはStack/QueueはSequenceには属さなさそう
Avatar
だね
Avatar
そもそもpush/popしか操作が許されてないから群ではあるけどSequenceではないね
Avatar
Sequence ではないですね。取り出さないと要素が得られないし。
Avatar
@mono その2にリンクしてあげるといいかもです。埋まってた人のための導線として。
https://qiita.com/advent-calendar/2017/swift done 🐶
(edited)
Taylorじゃない方のSwiftです( ´・‿・`)
👍 2
Avatar
通らないやつだ。
Avatar
norio_nomura 11/3/2017 1:46 AM
Standard Library内で活用するのが難しそうなまま通ることはなさそう。
Avatar
また is 周りで面白いの見つけてきた。
11:37 AM
長いのでGistに
Avatar
norio_nomura 11/4/2017 9:54 PM
パッケージのビルド要件をSwift 3.2以降としてしまった場合、Swift 3.2モードでビルド出来ることを維持する理由ってありますかね?
Avatar
omochimetaru 11/6/2017 1:35 AM
↑のResultのスレに いなみさんがポエムと称して長文を投稿してる
Avatar
どれ?
Avatar
omochimetaru 11/6/2017 1:36 AM
inamiy commented 2 days ago
I wrote a short poem for why I prefer typed error if you are interested: https://gist.github.com/inamiy/e3f5f7524f1bcdc582c2ff8dbbba58dd
👍 1
1:36 AM
MLじゃなくてPRスレッド
Avatar
ReactiveSwift - Streams of values over time
Avatar
NoErrorがtyped errorの最たるモチベーションなのは解るんだけど、それ故にNoErrorの実現のためにResultを導入するのはなんかなという気がする
Avatar
omochimetaru 11/6/2017 1:43 AM
俺も話しが拡大されてるように思った
Avatar
RxSwiftが引き合いに出されてるけどあれもthrows closureの有無でちゃんとやれば、Errorの有無をコンパイル時に〜というのは不可能ではないはず
Avatar
いなみさんが言ってるのは、 Result 導入するなら typed error が、って話であって、 Result が良い悪いではないのでは?
Avatar
今はできてないけど…
1:44 AM
typed errorに関しても、モチベーションの最たるところがNoErrorなので
1:45 AM
それはthrowの有無をちゃんとやれば良いだけなのではというお気持ち
Avatar
うーん、それは Result を直交概念から独立させれば良いのでは派。 Foo<Result<T>> // エラーが起こり得る Foo<T> // エラーが起こり得ない
Avatar
omochimetaru 11/6/2017 1:48 AM
Observable<Event, Failable: bool = true> Observable<Int> // may emit error Observable<String, false> // never error typealias NoErrorObservable<T> = Observable<T, false> NoErrorObservable<String> // never error 依存型があればこういう風にもできそう
1:50 AM
直交概念から独立させれば良いのでは派
Promiseならそれでいいけど、Observableだと、エラーだったら購読を切る、とか、制御自体が変化するから微妙じゃないですかね
1:51 AM
そういう場合だと、Resultを入れた場合で、かつ、それがエラーになったときだけ、特定の動作をする、っていう仕様は、隠し仕様っぽい感じでわかりにくくなりそう
Avatar
generic extension があればできない?
Avatar
@omochimetaru 依存型はまさにそうで、そこにthrowsの有無を組み込めばやりたいことはできる
Avatar
omochimetaru 11/6/2017 1:52 AM
実装は特殊化があればできるとは思います
1:52 AM
ユーザー側に型パラメータから道具の振る舞いが伝わりにくそうってこと
Avatar
実際そこはRxSwiftのAPIの問題なので
1:52 AM
型エラーの優位性の議論の引き合いに出せるレベルじゃないから
Avatar
omochimetaru 11/6/2017 1:53 AM
まあ、正面から NetworkFailure と InvalidJsonFormat を読み分ける話じゃないと、不足だよね
Avatar
その用途で現行のパターンマッチを超える話ならいけそう
1:54 AM
NoError軸は無理だと思う
Avatar
omochimetaru 11/6/2017 1:55 AM
typealias FailableFoo<T> = Foo<Result<T>> なら 見栄えの問題は解決するか
Avatar
ネストした map 等の煩わしさはあるけど、それも generic extension があれば一度に二重アンラップは用意できるはず。
Avatar
まあそこは現行でもワークアラウンドあるしなんとかできそう
Avatar
is こわれた import Foundation @objc protocol D {} class C: D {} C.self is D
Avatar
omochimetaru 11/6/2017 6:00 AM
すげえな、4行目
6:00 AM
Cast from 'C.Type' to unrelated type 'D' always fails
6:00 AM
always fails って言いながら true になった顔 🙄
Avatar
まじか
6:01 AM
C.init() is Dは?
Avatar
それはtrue
Avatar
omochimetaru 11/6/2017 6:01 AM
おかしいのは
6:01 AM
ふつうは C.self is D.Type
Avatar
import Foundation @objc protocol D { func hello() } class C: D { func hello() { print("hello") } } C.self is D (C.self as? D)?.hello()
Avatar
うん
Avatar
さてこれは
Avatar
omochimetaru 11/6/2017 6:02 AM
file:///Users/omochi/work/playground/TempGround.playground: error: Playground execution aborted: error: Execution was interrupted, reason: signal SIGABRT. The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
6:02 AM
死んだ
Avatar
アーメン
😇 1
Avatar
omochimetaru 11/6/2017 6:05 AM
そういえば ObjectiveC のときって
6:05 AM
self.class がメタクラスだけど、 self.class.class はループしてそれ自身を返さなかったっけ?
6:05 AM
そこらへんの絡みでなんかコンパイラ実装をミスってそう
6:28 AM
この関数な気がする
6:30 AM
3342行目で、 always fails のメッセージが出る > diagnose(diagLoc, diag::downcast_to_unrelated, origFromType, origToType)
6:30 AM
いや、むしろこっちは良くて、生成されるキャストが実行されたときの動きが変なのか
Avatar
omochimetaru 11/6/2017 7:21 AM
Resultのプルリクの件、同じ日にMLも投下されてた。
Avatar
Contribute to introduction-to-compilers development by creating an account on GitHub.
10:07 AM
これすごいw
10:08 AM
playground上で swiftのコンパイル後のバイナリを可視化する仕組みを作って
10:09 AM
その上でインタラクティブなplayground book形式のコンパイラ解説?記事?になってる
10:12 AM
あ、これ言語は swift っぽく見えるけど超サブセットっぽいな
10:14 AM
Parser, IRGen, Executor が入ってる。
Avatar
Adds a "strategy" for handling snake and camel case conversions for JSONEncoder and JSONDecoder. Proposal is available here: apple/swift-corelibs-foundation#1301
12:11 AM
オレオレエンコーダにも追加しよう。
Avatar
omochimetaru 11/7/2017 1:03 AM
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
1:03 AM
なるほどーこれは欲しい人多そう
Avatar
norio_nomura 11/7/2017 1:06 AM
もしかしてCodable側で制御できた方が嬉しいのかも。
Avatar
omochimetaru 11/7/2017 1:06 AM
それちょっと考えてました
1:07 AM
これはデコーダー側だから他のデコーダーには効かないですよね
Avatar
norio_nomura 11/7/2017 1:30 AM
キーの命名規約がエンコード先によって決まる事が多いなら、この提案の様にCoder側で解決した方が良いか。 (edited)
Avatar
omochimetaru 11/7/2017 1:31 AM
そうすると元々の機能の CodingKeys で 別の文字列を定義するやつはなんなんだろうという気もします
Avatar
norio_nomura 11/7/2017 1:31 AM
確かに…
Avatar
omochimetaru 11/7/2017 1:32 AM
デコードするフィールド名をリストする、という観点ではあらゆるシリアライズ先に共通だけど
1:32 AM
フィールドに対応する文字列を指定できるところは、共通でエンコーダー側に逃がすほうが一貫性がある気も。
1:32 AM
まあこういうのは使いやすければ細かいことはいいんだよ系な気もするけど・・・
Avatar
norio_nomura 11/7/2017 1:39 AM
MLに投げた。
Avatar
omochimetaru 11/7/2017 1:41 AM
Codable側にあったほうが良くない?側で投稿したんですね、なるほど
Avatar
norio_nomura 11/7/2017 1:43 AM
Codableとは関係ないenumrawValue自動生成メカニズムへと話が発展しそうな気がしなくもない。
Avatar
omochimetaru 11/7/2017 1:43 AM
あ、String rawvalueなenumって、codableだけの特別生成かと思っていましたが、
1:43 AM
もしかして自分でもそれできるんですか。
1:44 AM
Codableが特別なのは stored property にもとづいてCodingKeysのcaseリストを生成するところか。
Avatar
norio_nomura 11/7/2017 1:44 AM
そう。
1:46 AM
そうなると、snake_caseだけでなく、スペース区切りとかそういったバリエーションも考えられる。
Avatar
omochimetaru 11/7/2017 1:46 AM
camelCase と PascalCase とかもありますね。
Avatar
norio_nomura 11/7/2017 1:46 AM
Swift.Errorのエラーメッセージとか簡単になったりする>スペース区切り。
Avatar
omochimetaru 11/7/2017 1:47 AM
なるほど。
Avatar
omochimetaru 11/7/2017 2:31 AM
class Cat { init() { print(1) self.age = 3 // didSet呼ばれない print(2) self.age = { self.age }() // didSet呼ばれない print(3) self.refreshAge() // didSet呼ばれる print(4) self.age = { self.age }() // didSet呼ばれない ( これがちょっと変な感じ ) } var age: Int { didSet { print("age:did set") } } func refreshAge() { self.age = { self.age }() } } Cat()
🤔 1
2:31 AM
2番 の 時点でそもそも呼ばれると思ってた。(selfが完成するから)
2:31 AM
そしたら呼ばれなかったし、3の後の4も呼ばれないのはちょっと違和感
Avatar
3 は呼ばれるのに 2 と 4 呼ばれないのヤバめな感じが。 (edited)
Avatar
むしろなんで3は呼ばれるのか
Avatar
これは意図した挙動なのかなぁ?🤔
Avatar
omochimetaru 11/7/2017 2:33 AM
単純に、 「init からの呼び出しなら、 didSetは呼ばない」っていうルールが実装されていると思う
Avatar
@lovee 3が呼ばれないとセットアップ後に複雑なメソッド呼んだときにぶっ壊れる気がします。
2:34 AM
メソッド実装するときは普通 didSet 呼ばれる前提で書いているから、呼ばれない場合もあるというのは危険そう。
2:35 AM
セットアップ後はメソッド呼べるルールなんだから、セットアップ後は didSet も呼ばれるでもいい気もするんだけどなぁ。この仕様はどうなんだ? (edited)
Avatar
単純に、 「init からの呼び出しなら、 didSetは呼ばない」っていうルールが実装されていると思う
そう自分もそう思ってましたから3が呼ばれるのがすごい違和感というかなんというか
Avatar
↓みたいな構文の方がいい気がしてきた。 init(foo: Foo, bar: Bar) { // プロパティのセットアップ self.bar = bar } super(foo: foo) { // その後の初期化処理 }
Avatar
omochimetaru 11/7/2017 2:37 AM
お、C++っぽい
Avatar
C++ と違ってセットアップ部分に文が書けるのがいいところ。
Avatar
omochimetaru 11/7/2017 2:38 AM
そう自分もそう思ってましたから3が呼ばれるのがすごい違和感というかなんというか
そうですね、 init 「から」の、から、は、完全にダイレクトな意味で、呼び出しネストは考慮されない。
2:44 AM
破壊できそうな気がしてきた
2:49 AM
う、うーん、なるほど・・・
2:49 AM
stored property ( didSetを持つ ) 場合は、 その property が override されていても、 initから直代入だと 親の方は呼ばれない
2:50 AM
computed property ( get , set を持つ ) 場合は、override されていると、 init から代入すると親の方が呼ばれる
2:50 AM
一見不可解な挙動は生じるけど決定的に壊れるようなことは起こらない・・・↑の延長で説明できる事が起きた
2:51 AM
(もうちょっと破滅的な事が生じるなら報告してみようと思ってた
Avatar
norio_nomura 11/7/2017 2:57 AM
init() { defer { print("defer") self.age = { self.age }() // didSet呼ばれる }
Avatar
omochimetaru 11/7/2017 2:57 AM
defer www
2:58 AM
ん・・・?
2:58 AM
defer を末尾にかけば、その init制限空間から抜け出せるわけか。
2:58 AM
裏技だ・・・
Avatar
norio_nomura 11/7/2017 2:58 AM
この挙動はバグだ/バグじゃないとか、そんな話を最近読んだ。
Avatar
なんとなくだけどクロージャ書いてその中でsetしてクロージャ実行しても回避できそう
Avatar
@tarunon それが @omochimetaru の 2 じゃないですか?
Avatar
omochimetaru 11/7/2017 3:01 AM
class Cat { init() { defer { print("defer") self.age = { self.age }() // didSet呼ばれる } print(1) self.age = 3 // didSet呼ばれない print(2) self.age = { self.age }() // didSet呼ばれない print(3) self.refreshAge() // didSet呼ばれる print(4) self.age = { self.age }() // didSet呼ばれない ( これがちょっと変な感じ ) print(5); { self.age = self.age }() // didSet呼ばれる } var age: Int { didSet { print("age:did set") } } func refreshAge() { self.age = { self.age }() } } Cat()
3:01 AM
クロージャ正解
Avatar
2はメソッドだったので
Avatar
omochimetaru 11/7/2017 3:01 AM
なんとクロージャの中だと右辺をラップしなくてコンパイルできる
Avatar
おっと、これまで読み間違えてた・・・。 2 と 4 はクロージャ式の外で代入か。
Avatar
omochimetaru 11/7/2017 3:03 AM
defer の中と func の中は 右辺のラップが必要。
Avatar
omochimetaru 11/7/2017 3:11 AM
っていうか、didSetがあるときに
3:11 AM
self.age = self.age が棄却されるのは
3:11 AM
論理的におかしい気がしてきた
3:11 AM
副作用があるんだから。
3:12 AM
そこだけ報告しようかな
Avatar
norio_nomura 11/7/2017 3:37 AM
この挙動はバグだ/バグじゃないとか、そんな話を最近読んだ。 Twitterだった。この辺り https://twitter.com/jckarter/status/926459181661536256
@johnsundell That’s a bug that’ll be fixed soon. The more reliable way to do it is to call a method that sets the property.
Avatar
omochimetaru 11/7/2017 3:38 AM
Joe Groffがバグじゃ〜って突っ込んだらSlavaがいやいや、って突っ込んでるのかw
Avatar
norio_nomura 11/7/2017 3:41 AM
結論は良くわからない(最後まで追ってない)けど、とりあえず使わないでおこうと思った。
Avatar
3の挙動が正しいってのは一致してそう。
Avatar
3 は正しいと思います。
3:46 AM
僕は 2 と 4 も didSet 呼ばれて、↓も呼ばれてもいいと思います。 print(1.5) self.age = 4
Avatar
omochimetaru 11/7/2017 3:47 AM
initの中で self が使えるようになった以降と以前でその挙動を変えるべきってことですよね
Avatar
はい。
Avatar
omochimetaru 11/7/2017 3:47 AM
たしかに、僕もそもそもはそれを期待していた。
3:47 AM
あー、やるならそのレベルの意見提案としてML投下が一番いいか・・・
Avatar
ただ、 super.initself.init がないと可読性がヤバイので、メソッド呼ぶには self.init() が必須とかの方がいいかも?
Avatar
omochimetaru 11/7/2017 3:48 AM
initの中で self. init 呼んだら 無限ループ風にみえます
Avatar
そうだねー
3:48 AM
何かいい記法があればいいんだけど。
Avatar
問題は、現状didSet呼ぶルートに流すのはSemaだけど、Sema時点では self が完成しているか分からないので、やるなら大工事が必要ってことですね。
Avatar
omochimetaru 11/7/2017 3:50 AM
class Cat { init { selfが使えない } didInit { selfが使える } }
3:51 AM
スコープが切れちゃうからコンストラクタ引数とか困るな・・・
Avatar
現状でもイニシャライザで self のメソッド呼べるかチェックされてるのに、同じようにチェックはできないんでしょうか?
3:51 AM
@omochimetaru うん、スコープ切れる問題さっき考えてた。
🤒 1
3:53 AM
super.init() を書かないといけないとかだと無限ループ問題はなくなるかも。 struct だと何これ?ってなるけど。
3:53 AM
暗黙のスーパータイプ Any
Avatar
omochimetaru 11/7/2017 3:54 AM
現状でも self 完成を明記する記法は結構欲しいんだよな
3:54 AM
書いたときの気持ちをコードに残しておきたい
Avatar
それ系のチェックはSILでコントロールフロー作ってからやってるので、通常のアサイメントに流すか、ストレージにダイレクトに格納するかをSIL以降に決定する必要がある。
Avatar
うん、ほしい。
Avatar
新しい記法作らないと source breaking になっちゃうので、新記法で縛った方が通りやすいかもですね。
Avatar
それでも didSet 呼ばれるようになったら source breaking ですよねぇ😣
Avatar
omochimetaru 11/7/2017 3:58 AM
例えば新しい inited(self) とかを導入した上で、 Swift4 では、 inited(self) が書いて無ければ、これまでどおりの挙動+警告、 inited(self) が書いてあれば 新しい挙動、 Swift5では、 inited(self) が必須
3:59 AM
とやれば、既存のコードは inited(self) を書いていないので、移行期間の下位互換は取れる (edited)
Avatar
なるほど。そういうことか。
Avatar
omochimetaru 11/7/2017 3:59 AM
super.initinited(self) の両方を書きたくないなあ・・・
Avatar
うん・・・
Avatar
条件分岐中のinited(self)とかあるとめんどくさいので、didInit {} の方がいい気がするけど、特定のイニシャライザだけで後処理したい時にめんどくさそう。
Avatar
omochimetaru 11/7/2017 4:05 AM
あー分岐かあ・・・
Avatar
didInitinit に付随するイメージでした。
4:05 AM
でも、コンストラクタ引数が渡せないの辛そう。
4:06 AM
ネストすればいいのかな?
Avatar
norio_nomura 11/7/2017 4:06 AM
普通にメソッド作った方が良さげ
Avatar
@norio_nomura 確かに、初期化完了後の処理をすべてメソッドに切り出すというワークアラウンドはありますね。 (edited)
4:07 AM
ってか、クロージャ式でいいのか。
Avatar
omochimetaru 11/7/2017 4:07 AM
メソッドだとinit以外から呼ばれる可能性が生じちゃうのですよね
4:07 AM
インナーfunc とかがいいかな。
Avatar
init(...) { self.foo = ... super.init(...) { // self を使う処理( didSet も有効) }() }
4:10 AM
やっぱり run がほしくなるな。 func run(_ operation: () throws -> ()) rethrows { operation() } (edited)
Avatar
omochimetaru 11/7/2017 4:10 AM
↑それ、 super.init と後ろのクロージャがくっついちゃうから
4:10 AM
super.initの右に ; が必要かも
Avatar
ひどいw < くっついちゃう
Avatar
omochimetaru 11/7/2017 4:10 AM
runがあれば解決。
Avatar
init(...) { self.foo = ... super.init(...) run { // self を使う処理( didSet も有効) } }
Avatar
omochimetaru 11/7/2017 4:11 AM
runが無いと単発即時クロージャが直前の関数呼び出しにくっついちゃう問題があるんですよね
Avatar
=>run がほしい。
Avatar
init(....) { init { ... } didInit { ... } } プロパティの構文に似せてみた
4:48 AM
initの中で記述するのがポイントかしら
Avatar
そうですねぇ。その構文ならイニシャライザ引数が使えるのがいいけど、 init が異なる意味で二箇所で使われてしまうのと、 init {}didInit {} で変数を共有できないあたりが微妙でしょうか。
Avatar
didInit欲しい
7:19 AM
というか UIView にも UIViewControllerviewDidLoad と同等なものが欲しい
Avatar
omochimetaru 11/7/2017 7:20 AM
addToWindow で フラグつかって1回だけやるとか
Avatar
xib使うなら awakeFromNib だとおもうけどloveeさんだとどうかはわからない
🙃 2
Avatar
awakeFromNibとviewDidLoad微妙にタイミングが違うからなー
Avatar
async/awaitの根っこの
10:13 AM
coroutine 機能の実装が、 SILレベルで進んでる
10:13 AM
ていうかSILレベルだとcoroutine展開されないんですね。
Avatar
お、早めに beginAsync の rethrows の件ポストしないと。
Avatar
omochimetaru 11/7/2017 5:59 PM
gysb - Generate your swifty boilerplate
👀 4
5:59 PM
Swift実装のgybを作った!テンプレートコードはSwiftで書けるので型エラーとか出る。
Avatar
beginAsyncrethrows の件書いてみました。いかがでしょう?( swift-evolution 未投稿です) https://gist.github.com/koher/bcb0ac8c05a4e43b6c5a40bcac041285 (edited)
Avatar
いいですね。
In following cases, beginAsync just has to crash the program when foo throws an error.
のくだりのあとぐらいに、 「rethrowsが含まれるコードのコンパイルが通っているのにクラッシュする可能性が残るというのはSwiftの検査例外の安全な世界を破壊してしまうし」 ってもうひと押しあると良いと思いました。 あと、
If beginAsync does not rethrow errors
に 「つまり、引数のbodyがthrowsで無いならば」 を付け足したほうが正確だと思います。 beginAsyncはrethrowsではないがbodyはthrowsという状態もシグネチャだけで言えばありえるからです(その場合、キャッチされた例外は全てクラッシュになるので今より悪くなるだけだけど)
Avatar
なるほど。修正して投稿します。
Avatar
返事があった。
FWIW, I also still think it would be better if we allowed for async void functions instead of requiring beginAsync in the first place. If I had my way then we would have async void, but an async void would not be allowed to throw.
これについては Swift においてはおかしなことになると思う。 () async -> Void をやりたいケースが普通にあるはずだし。
Avatar
omochimetaru 11/8/2017 5:52 AM
この英文は beginAsyncが無くても () async -> Void な関数をいきなり呼べるようにしたらええんちゃうって意見であってますか? (edited)
5:53 AM
Swiftでそれやったら、 await 忘れてうっかり呼び出しちゃってるケースと
5:53 AM
曖昧になって残念すぎる
5:53 AM
かといって、async Void のときに await つけたら、それこそ意味不明な見た目になるし。
Avatar
そうだと思います。 C# だと async で戻り値 void だと await できないから。
5:55 AM
かといって、async Void のときに await つけたら、それこそ意味不明な見た目になるし。
ん?別に問題ないのでは? beginAsync { await foo() await bar() }
5:55 AM
今の try も同じだし。
Avatar
omochimetaru 11/8/2017 5:55 AM
beginAsyncが無い話ですよね?
5:55 AM
↑はbeginAsyncがついてるから普通。
Avatar
ああ、 beginAsync なくしたときに await 付けて代わりに直接呼べるようにしたらって話か。
Avatar
omochimetaru 11/8/2017 5:56 AM
そうです。
Avatar
それはアウトだね。外側が async じゃないとコンパイルエラーになってほしいし。
Avatar
omochimetaru 11/8/2017 6:24 AM
投稿した
👍 1
Avatar
filterMapmutating 版を考えてたんだけど、 inout 使うなら↓とかかな? mutating func updateOrRemove(_ f: (inout Element?) -> Void)
7:53 AM
inout なしなら↓だけど。 mutating func updateOrRemove(_ f: (Element) -> Element?)
7:53 AM
mapmutating 版は↓。 mutating func update(_ f: (inout Element) -> Void)
Avatar
クロージャ内で= nil したら消える? どんな実装になるんでしょう?
Avatar
クロージャ内で= nil したら消える?
そう。だけど効率考えたら微妙そうだね。 (Element) -> Element? の方が良さそう。
7:55 AM
でも、 mapmutating 版は inout になると思うんだよなぁ。
Avatar
mutating版は型の制約がついて使いにくい感じありますけどねぇ 用意してもらわなくてもいいかな?と
Avatar
WWDC のビデオでも↓が出てくる。 < inout になると思う mutating func modifyEach(_ body : (inout Element) -> ()) (edited)
7:57 AM
map よりもパフォーマンス良くなるからニーズはあると思う。 < 用意してもらわなくてもいい (edited)
Avatar
パフォーマンス求めるならforで書きますけど インライン化されたら同等ならあったほうがいいかな?
Avatar
for で書いてもインデックスでアクセスするから遅いんじゃない?
7:59 AM
ポインタでアクセスしたときと同等にできるんじゃないかなぁ。
Avatar
あーforを飛ばしてポインタと同等までに行ける可能性もあるか
Avatar
うん。それってパフォーマンスと利便性を兼ね備えた素晴らしい API だと思うんよね。
8:00 AM
mutating func update(_ f: (Element) -> Element) でもいいかもしれないけど。
Avatar
それだとreturn後の代入が必要なわけですよね
Avatar
はい。最適化でクロージャ式がインライン化されて同じにならないかな? (edited)
Avatar
elementを弄った後return elementするのが嫌な感じが
Avatar
あー、確かに element のプロパティの一部を書き換えるとかだとそうだね。やっぱ inout がいいか。
8:04 AM
うーん、やっぱ↓を考えると一貫性持たせるの難しいな・・・。 mutating func updateOrRemove(_ f: (inout Element?) -> Void) mutating func updateOrRemove(_ f: (Element) -> Element?)
Avatar
[Element](inout Element?) -> Voidを呼んだ場合の実装がやっぱりよく分からない
8:08 AM
一度[Element?]を作るなら明らかにパフォーマンス悪いですよね
Avatar
そうだね。一度 Optional に入れてから戻すとかでパフォーマンス悪そう
8:08 AM
ってか、 mutating 版自体がおかしいか?
8:08 AM
削除を考えてると作り変えて差し替えた方がパフォーマンス良さそう
8:08 AM
なので filterMap さえあればいいかも。
Avatar
extension Array { mutating func updateOrRemove(f: (inout Element?)->Void) { withUnsafeMutableBufferPointer { var src = $0.baseAddress! var dst = $0.baseAddress! for _ in 0..<$0.count { var e: Element? = src.pointee f(&e) if let e = e { dst.pointee = e dst += 1 } src += 1 } } } } これ+カウント書き換えならそこそこかな? (edited)
8:10 AM
なんかarray縮めるやつありますよね
Avatar
array 縮めるって O(N) じゃないの?
Avatar
そこはよく知らないですね……
Avatar
omochimetaru 11/8/2017 8:13 AM
隙間を埋めるならinplaceで前に寄せればいいからO(N)
Avatar
↑の実装だとarrayの後ろの方を消すだけですね
Avatar
やっぱ filterMapmutating 版はないな。 O(N^2) になっちゃう。
8:14 AM
filterMap なら O(N)
8:15 AM
もちろん、 filterMap を内部で使って自身を差し替えで O(N) にはできるけど、それなら filterMap 使って自分でやればいいし、メソッドになってる意味がない。
8:16 AM
ただ、 Array にとってはナシだけど、 LinkedList なら有用。
Avatar
var ary = [1,2,3,4,5,6,7] for var elem: Int? in ary { print(elem) } 破壊した
8:38 AM
※無限ループ注意
Avatar
手遅れだったw < 無限ループ
😖 1
Avatar
omochimetaru 11/8/2017 8:40 AM
え、なにそれ・・・w
8:41 AM
next()の返り値が格納できちゃうって感じ?
Avatar
Iteratorの吐く Int?.noneをInt??にキャストするときに
Avatar
: Int? が書けることが邪悪だー
Avatar
違うか、Int??すら出てきてなさそう
8:45 AM
var elemn: Int? = iterator.next() as? Int? // 当然成功する こうかな (edited)
Avatar
っぽいですね。
Avatar
ほんと Int is Int? は封じないとヤバイ気がしますね。 (edited)
8:50 AM
型システムがぶっ壊れてる・・・。
Avatar
ボクじゃない誰かがボクの代わりにOptionalManifestを書いてもいいと思います
8:50 AM
まだ事案まとめぐらいしか出来てない
Avatar
inout 版はクライアント側の使い勝手が微妙ですねぇ。 // (inout Element?) -> Void 版 extension Array { mutating func updateOrRemove(_ f: (inout Element?) -> Void) { var writeIdx = startIndex for readIdx in indices { var elem: Element? = self[readIdx] f(&elem) if let elem = elem { self[writeIdx] = elem writeIdx = self.index(after: writeIdx) } } removeLast(distance(from: writeIdx, to: endIndex)) } } var ary = [1,2,3,4] ary.updateOrRemove { (elem) in if elem! % 3 == 0 { elem = nil return } elem! *= 10 } print(ary)
Avatar
Optional は暗黙の型変換は許す、サブタイピングは許さない、がちょうど良い着地点な気がする。
Avatar
型変換というか
8:51 AM
暗黙の.someラッピングですね、それだけ許して後は封印
Avatar
こっちの方がいい // (Element) -> Element? 版 extension Array { mutating func updateOrRemove(_ f: (Element) -> Element?) { var writeIdx = startIndex for elem in self { if let elem = f(elem) { self[writeIdx] = elem writeIdx = self.index(after: writeIdx) } } removeLast(endIndex - writeIdx) } } var ary = [1,2,3,4] ary.updateOrRemove { (elem) in if elem % 3 == 0 { return nil } return elem * 10 } print(ary)
Avatar
あーそういうことか。
8:53 AM
それなら確かに O(N) でできる。 @t.ae のもそうなってるのか。読めてなかった。
8:55 AM
うーん、 inout 版も悪くないような気が。 return が微妙ってことですか? < inout 版はクライアント側の使い勝手が微妙ですねぇ。
Avatar
渡ってきた Element? をいちいちアンラップしないと値が読めないのはきついと思います。
Avatar
ああ、確かに。 ! 付いてますね。
8:57 AM
しかし、そうなると inout 版の update がほしいのに filterMap だけ inout 版にならないのイマイチですねぇ☹
Avatar
(inout Element!) -> Void っていう手もありますが、嫌ですよねw
Avatar
それはそれでヤバげだけど、意外と問題がない気も。
Avatar
Optionalのmap/flatMapにinout版があれば済みますよ
Avatar
その Element! 、かなり特殊な使い方ですね〜。おもしろい・・・。
Avatar
というかinout reduceは他の構造のメソッド全部inout版作ってからが本番なので
Avatar
二重 update するのか・・・ < Optionalのmap/flatMapにinout版があれば済みますよ
Avatar
var x: Int! = 12 x += 12 // error: binary operator '+=' cannot be applied to operands of type 'Int!' and 'Int' っていう問題もあり。
Avatar
↓こう? < Optionalのmap/flatMapにinout版があれば ary.updateOrRemove { (elem) in elem.updateOrRemove { $0 = $0 % 3 == 0 ? nil : $0 * 10 } }
Avatar
そんな感じ!
Avatar
これは可読性ヤバそうw
Avatar
$0使わなければ
9:05 AM
ary.updateOrRemove { (x) in x.updateOrRemove { (elem) in if elem % 3 == 0 { elem = nil } else { elem *= 10 } } } 普通に読めると思う (edited)
9:05 AM
インデント崩壊した
Avatar
うーん… extension Array { mutating func updateOrRemove(_ f: (inout Element, _ remove: inout Bool) -> Void) { var writeIdx = startIndex for readIdx in indices { var remove = false f(&self[readIdx], &remove) if writeIdx != readIdx { self[writeIdx] = self[readIdx] } if !remove { formIndex(after: &writeIdx) } } removeLast(distance(from: writeIdx, to: endIndex)) } } var ary = [1,2,3,4] ary.updateOrRemove { (elem, remove) in if elem % 3 == 0 { remove = true return } elem *= 10 } print(ary)
Avatar
レトロ感
Avatar
removeを関数にするとか・・・
Avatar
Optionalでラップするとサブスクリプトの最適化が効かない気がするんだよね
Avatar
omochimetaru 11/8/2017 2:15 PM
http://twitter.com/omochimetaru/status/928264127591485441 書きました。みなさんの gyb 情報を引用させていただきました。
Swift で書けるメタプログラミング向けのテンプレートエンジン gysb を作った by @omochimetaru on @Qiita https://t.co/eVAaY12b1W #swift
Avatar
なぜか全員ここの住人やね
Avatar
omochimetaru 11/8/2017 2:17 PM
それ
Avatar
テストが欲しいね>gysb
Avatar
gybのテスト真似したら良いのかな
Avatar
norio_nomura 11/9/2017 1:30 AM
apple/swiftの場合、swiftのビルド自体がgybのテストみたいなもので、gyb単体でのテストはなさげ?
Avatar
doctest は一応動かしているはずです。
Avatar
norio_nomura 11/9/2017 2:03 AM
最低限だw
Avatar
omochimetaru 11/9/2017 2:03 AM
テスト欲しいですね テンプレートコンパイルの周りはふつうにSwiftPMで書けるけど、 gysbコマンド自体のテストは一個外側の仕組みが必要ですね
Avatar
@omochimetaru ↓参考にならないかな? https://github.com/kylef/Commander
Commander - Compose beautiful command line interfaces in Swift
Avatar
omochimetaru 11/9/2017 2:04 AM
あーでもまあコマンドの直下までは普通に書けるか
Avatar
omochimetaru 11/9/2017 2:14 AM
@koher 普通にモジュール単位でSwift内部でテストしてるように見えます
Avatar
実際にテスト用のコマンド作ってそれを実行するテストがあったりするのかと思ったけどそういうわけではない?
Avatar
omochimetaru 11/9/2017 2:21 AM
そういう実用レイヤのやつは無さそう スマホでちょっと見ただけだから見落としたかもしれません。
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 11/9/2017 3:23 AM
protocol ASTNode : CustomStringConvertible { func accept<V: ASTVisitor>(visitor: V) -> V.VisitResult } protocol ASTVisitor { associatedtype VisitResult func visit(nop: NopNode) -> VisitResult func visit(text: TextNode) -> VisitResult func visit(code: CodeNode) -> VisitResult func visit(subst: SubstNode) -> VisitResult func visit(macroCall: MacroCallNode) -> VisitResult func visit(macroStringLiteral: MacroStringLiteralNode) -> VisitResult func visit(template: Template) -> VisitResult } (edited)
3:23 AM
Visitorパターンの素体を protocol で組めて、 associatedtype で返り値の型もジェネリックにできて、ここまでは良かったんだけど
3:23 AM
throws / rethrows が適用できない事に気がついた・・・
3:24 AM
もし Node に渡す Visitor が 例外を投げうるVisitor であれば、 Node.acceptは throws になってほしい。
3:25 AM
ASTThrowableVisitor protocol を定義して accept をオーバーロードすればいけるか・・・?
3:25 AM
全部のノードに accept の実体を2倍かかないといけないけど。
Avatar
型をわける
3:28 AM
理論上は() throws -> T の特殊な状態として () ->T があると定義できるので
3:29 AM
ASTThrowableVisitor protocol を定義して accept をオーバーロードすればいけるか・・・?
これやね
Avatar
omochimetaru 11/9/2017 3:29 AM
struct TextNode : ASTNode { var text: String func accept<V: ASTVisitor>(visitor: V) -> V.VisitResult { return visitor.visit(text: self) } var description: String { return "Text(\(escapeToSwiftLiteral(text: text)))" } } (edited)
3:30 AM
こういう、個別のNode型から visitor.visit の呼び戻しを書く必要があるんだけど
3:30 AM
これ全部 ThrowsableVisitor 用も必要になるよね。
Avatar
そうやね
3:30 AM
ASTVisitor
3:30 AM
これを単なる関数として定義すれば
3:30 AM
throws - rethrowsで書けそうだけど
Avatar
omochimetaru 11/9/2017 3:39 AM
型ごとにいっぱいメソッドがある Visitor だから
3:39 AM
単なる関数にはならんのだよね
Avatar
https://github.com/swift-script/swift-script/blob/master/Sources/SwiftAST/Visitors.swift これで throws じゃない Visitor もconform できたけど、そういう話じゃない?
Avatar
返り値VisitResultだから引数enumにしたらいけそうなもんだけど
Avatar
omochimetaru 11/9/2017 3:40 AM
@rintaro これだと、実際にはthrowsしないVisitorにおいても、throwsしちゃうから、 try 必要ですよね
3:41 AM
まあ throws しない Visitor なんて無いやろって感じもあるけど・・・
3:43 AM
ああ、そうですね < try 必要ですよね
3:43 AM
Contribute to swift-script development by creating an account on GitHub.
Avatar
omochimetaru 11/9/2017 3:44 AM
ですよね〜
Avatar
とはいえ、クライアントが Visitor を生で使うことはあまり考えられず、 普通はラッパ関数通して使うし、ラッパ関数はその Visitor が実際に throw するか否かは分かると思うので、いいかなという気がする。 (edited)
Avatar
omochimetaru 11/9/2017 3:48 AM
たしかに・・・
3:48 AM
それはめっちゃそうな気がしてきた
3:49 AM
throwsつけちゃお
3:49 AM
ありがとうございます
👍 1
3:50 AM
extension ASTNode { func print() { // Printer never fail try! accept(visitor: ASTPrinter()) } }
3:50 AM
こういうわけですね。
3:51 AM
コメントだとあれだからアレしとこ
Avatar
fails では?
Avatar
omochimetaru 11/9/2017 3:54 AM
英語?
Avatar
英語
Avatar
omochimetaru 11/9/2017 3:54 AM
たしかに。
Avatar
gysbくらいの規模のASTならいっそenumにしてしまって、Vistorパターン使わずパターンマッチ使うという手もあるかもですね!そしたらthrowするしないも使う側で適当に決めれますし
Avatar
omochimetaru 11/9/2017 4:02 AM
たしかに・・・
4:04 AM
きれいなVisitorパターンをやってみたかったという動機が大きいです
👍 1
Avatar
protocol ASTNode : CustomStringConvertible { func accept<V: ASTThrowsVisitor>(visitor: V) throws -> V.VisitResult } extension ASTNode { func accept<V: ASTVisitor>(visitor: V) -> V.VisitResult { return try! accept(visitor: visitor) } } これでさ、
4:08 AM
protocol ASTVisitor: ASTThrowsVisitor { associatedtype VisitResult func visit(nop: NopNode) -> VisitResult ... } extension ASTVisitor { func visit(nop: NopNode) throws -> VisitResult { return visit(nop: nop) } } こうしたらいけないかね
4:09 AM
protocol ASTThrowsVisitor { associatedtype VisitResult func visit(nop: NopNode) throws -> VisitResult .... } これ忘れてた
Avatar
omochimetaru 11/9/2017 4:09 AM
あ〜
4:09 AM
投げない側がサブタイプなのか
Avatar
理論上は() throws -> T の特殊な状態として () ->T があると定義できるので
4:10 AM
サブタイプ扱いにしてしまえばなんとかなるかな?と
Avatar
omochimetaru 11/9/2017 4:10 AM
accept 呼び出すところで 、型がキツイ方のオーバーロードが優先されるはずだから
4:10 AM
うまくいく気がする!!
👍 1
4:15 AM
あれか、 ASTVisitor を実装するときに、例外を投げちゃいけない事を、静的に強制できない?
Avatar
ん?あー
4:19 AM
できない。。。かも
Avatar
omochimetaru 11/9/2017 4:19 AM
あと、 extension ASTNode { func accept<V: ASTVisitor>(visitor: V) -> V.VisitResult { return try! accept(visitor: visitor) } }
4:19 AM
ここで怒られた、名前解決が同じやつになっちゃって
Avatar
ありゃー
Avatar
omochimetaru 11/9/2017 4:19 AM
accept例外投げんぞ?tryいらんで
4:19 AM
っていわれたので
4:19 AM
まあメソッド名を変えました
Avatar
だめか
4:20 AM
available駆使して、throwついてる方の呼び出しをどうにか禁止できれば
4:20 AM
まあそれっぽくなるかなと思ったけどまだavailableにアクセス修飾子漬けれないしムリくさい (edited)
Avatar
omochimetaru 11/9/2017 4:21 AM
まあ完璧ではないけどかなり良い感じ
Avatar
omochimetaru 11/9/2017 6:38 AM
やべえ
6:38 AM
enum case の let 先置き派として
6:38 AM
気がついてしまったんだけど
6:39 AM
switch x { case let . // ← let があるとここでドットを入力しても補間が出ない・・・
Avatar
よし、先置き辞めよう
6:39 AM
これでようやく心を入れ替えれるね
Avatar
omochimetaru 11/9/2017 6:39 AM
case かいて ドット打って補間してから  ←に戻って let を打たないといけない・・・
Avatar
letは中、いいね?
Avatar
omochimetaru 11/9/2017 6:40 AM
なんてこったい
Avatar
おお? print(["ab", "cd"].flatMap { return $0 }) // ["a", "b", "c", "d"] print(["ab", "cd"].flatMap { $0; return $0 }) // ["ab", "cd"] https://twitter.com/gregheo/status/928787861507207168
Swift observer effect at work: 😜 print(["ab", "cd"].flatMap { return $0 }) // ["a", "b", "c", "d"] print(["ab", "cd"].flatMap { $0; return $0 }) // ["ab", "cd"]
Avatar
ぉおー、後者は クロージャの return type が Any とかに infer されてるのかな?
1:39 AM
ちがうか、(String) -> String? として扱われてて、呼び出される flatMap が違う。
Avatar
やはり
1:47 AM
型として変性が認められるもの(クラスなど)と、値としてのみ変性が認められるもの(Optionalなど)にわけて、前者だけ関数・ジェネリクスの変性に使えるようにすれば
1:47 AM
大分平和になりそうだなというのを朧気に考えていた
Avatar
前者はSequence.flatMap<SegmentOfResult: Sequence>(_ transform: (String) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] 後者はCollection.flatMap(_ transform: (String) throws -> String?) rethrows -> [String]
1:44 PM
Codableが、 Optional なら キーの省略を none と扱うように、 Array の場合にもキーの省略を空配列として扱ってほしかったが、 エラーになるので、キーが省略されたら空配列としてデコードできるように↑のように書いたんだけど、もっと記述量少なく、やる方法ってありますか?
Avatar
素直にinit(from:)を書いた方が良いのでは。
Avatar
decodeIfPresent と ?? [] か・・・
Avatar
あれ?自分でやる場合、KeyedContainerの nestedUnkeyedContainerを呼び出すんですよね?
2:47 PM
あ、普通にdecodeIfPresentに[Stone].self とかわたせばいいのか
Avatar
#if os(Linux) class A #else @objc class A : NSObject #endif { }
4:41 AM
これがコンパイルできないんですけど良い方法ありますか?
4:42 AM
Foundation.Threadを使おうとしているが、Macの場合は init(target:selector:) を使う必要があるので @objc が必要
4:42 AM
Linuxの場合は init (block:) でいけるので不要
Avatar
Kishikawa Katsumi 11/11/2017 4:42 AM
これは2つ書くしかないんじゃなかったかな。
4:42 AM
#if os(Linux) class A { } #else @objc class A : NSObject { } #endif
Avatar
ンゴ・・・
4:43 AM
了解です、今そうなっちゃってるんですが、とりあえずそのままで。。
Avatar
Kishikawa Katsumi 11/11/2017 4:44 AM
将来的にはわからないけど、 #if はCのプリプロセッサみたいに何かの途中で、とかはできなかったです。
Avatar
ある程度構文上の制約があるんですね
4:46 AM
まあそのほうが、IDEとか安定しそう。
Avatar
NSBlockOperationとか使って共通化出来ない?
Avatar
お・・・
Avatar
やりたいことできるかわからんけど https://developer.apple.com/documentation/foundation/blockoperation
Avatar
スレッドはどうしても立てる必要があるんだよね
Avatar
Kishikawa Katsumi 11/11/2017 4:48 AM
GCDじゃダメなんです? (edited)
Avatar
別プロセスからパイプを読み出したい
4:49 AM
あ〜
4:50 AM
よくわかっていないんですけど、DispatchQueueって、
4:50 AM
すぐに終了しない、ブロックする関数を投げてもうまく動くんですか?
4:50 AM
細切れで何度も再入するようなタスクにしてやらないと
4:51 AM
キュー達に対する下請けの実ワーカースレッドの割当スケジューラが
4:51 AM
詰まっちゃう気がしています
4:52 AM
言い換えると、キュー一本に専用のスレッドが一個確保されることを保証したモードはあるか、という事
Avatar
Kishikawa Katsumi 11/11/2017 4:55 AM
1つのキューがずっと同じスレッドかどうかの保証はなかったと思います。
4:55 AM
もともとやろうとしてることは1つのNSThreadで待つつもりなんですよね?
Avatar
そうですね
Avatar
Kishikawa Katsumi 11/11/2017 4:56 AM
同じようにGCDのクロージャで待てばいいと思いますよ。
Avatar
なるほど
4:57 AM
あー、足りなければスレッドが生まれて、遊んでれば再利用みたいな制御なのかな・・・?
4:57 AM
固定数のスレッドプールがあるわけではなくて。
Avatar
Kishikawa Katsumi 11/11/2017 4:58 AM
私の言いたいことは、NSOperationはNSThreadよりも高級だけど、GCDとNSThreadと同等なので、今はNSThreadを直接使うということはしないんじゃないかなということです。
Avatar
まあ原則はそうですよね
5:03 AM
SwiftPMの内部で、外部プロセス立ち上げて、stdoutを吸い出すのにスレッドを立てているんですが、 単にDispatchの実装を待ってられないから独自に用意したんだろうか
5:04 AM
こういうところでたまに見るので、逆に生スレッドのほうがいいユースケースがあるのか、それともどんなユースケースでも絶対に上位互換になるのか
5:04 AM
そのへんの境界が正確にわかっていなくて、
5:05 AM
よくわからない場合はできるだけシンプルな道具を使ったほうがいいと思っているので悩みます。
5:07 AM
もともとの質問にあった NSThread が二重定義になってしまう問題については、継承して func main をオーバーライドするパターンなら共通コードにできることに気がついて解決しました。 ありがとうございました。
7:05 AM
+extension Optional : Equatable where Wrapped : Equatable { + /// Returns a Boolean value indicating whether two optional instances are + /// equal. + ///
7:05 AM
↑いい感じ!
😍 3
Avatar
4.1に含まれてほしい!
😄 2
Avatar
別プロセスからパイプを読み出したい こんな感じにしてる https://gist.github.com/norio-nomura/90a374d33c5178fdbc336b1e50cf74dc
Avatar
PipeがFoundationのやつじゃなくて自作なんですね。 DispatchIOだ。使ったことない。
Avatar
Foundationのものはクローズが判らなかったので、自作したと記憶。
Avatar
クローズした場合長さが0の Data が来ると思っていました。
8:04 AM
思っていた、っていうか、今そういう前提で書いています。
8:04 AM
let stdoutPipe = Pipe() let stdoutThread = Thread { while true { let chunk = stdoutPipe.fileHandleForReading.availableData if chunk.count == 0 { break } stdout(chunk) } } stdoutThread.start()
Avatar
今のはそう動きますね。以前のは違ったらしい。
Avatar
↑こう
8:04 AM
ああ、なるほど。
8:05 AM
readabilityHandler が実装されてればそもそもスレッドもいらんかったんですが
8:05 AM
Linux版はまだ NSUnimplemented になっていました
Avatar
あ、Linuxで動くかどうかは確認していないです。
8:09 AM
単純に出力全部を最後に取得するだけなら、こんなのは必要なかった。
8:10 AM
リアルタイムで外部へ流しながらキャプチャするために作った。
Avatar
ああ。僕もまさにその目的です。
4:44 AM
クリスラトナーが、他の動的言語とブリッジするための仕組みの、Swift側のシグネチャについてのプロポーザルを投下してめちゃめちゃ盛り上がってる 具体例としてはPythonをそのままSwiftコードとして呼び出す事を想定している。
4:45 AM
Joe Groffが、その前に静的な Callable Object について整備したほうがいいって言ったり、 Slava Pestov が、関数呼び出しの種類がもう一個増えるのは厳しい、って言ったり
4:52 AM
SwiftML読んでて思うけど大筋反対の意見に対してもその中にあるアイデアを拾ってそれは大事だね!みたいな感じで紳士的に進んでいくのすごい
Avatar
https://twitter.com/clattner_llvm/status/929221571964628992 ちょっと場外戦に発展しちゃってる。
@jckarter @slava_pestov @JadenGeller I love working in open and inclusive communities which are friendly and encouraging towards open source contributors. I hope swift will get one someday. 😳
Likes
119
Avatar
おや。合間合間に読み進めているのでまだスレ追いつけてないw
Avatar
↑のツイートきえてた。
1:46 AM
スレでもツイートでも すまなかった みたいな感じになってて良かった
Avatar
LazySequenceProtocolがSequenceを継承しているの辞めたほうが良いのではと思ってるんですがどうですかね
Avatar
@tarunon 問題点はどこですか?
Avatar
Sequence.FilteredSequenceとか高階型が出来たとして
1:24 AM
それらの結果がLazySequenceの類であるためには、
1:24 AM
引数のクロージャが@escapingでなければならない、 (edited)
1:25 AM
現状も全部オーバーロードしていて、あまりよろしくないのでは、という気がしています
1:28 AM
どちらかというと、問題は Sequence にデフォルト実装されてるメソッド群だと思うんですよね。純粋に makeIterator を持つだけの型がほしい。
Avatar
それはそうですね
1:28 AM
だから、makeIteratorを持つだけの型をベースに
1:29 AM
SequenceとLazySequenceをその継承として再設計、というイメージでした
1:29 AM
えーっと見分け方は、基本的には条件が厳しい方が優先なので
1:29 AM
LazySequenceなら特に外から制約が加わらない限りは、LazySequenceのオーバーロード群が優先されそうです。
Avatar
問題は Sequence にデフォルト実装されてるメソッド群
どれもmakeIteratorから機械的に生成できるものをSequenceの場合に最適化版を生やしているだけじゃないんですか?
1:30 AM
なぜそれが問題になる?
Avatar
それはLazySequenceにとっては邪魔なのでは?という点です
1:31 AM
LazySequenceのprefixにArray/AnySequenceが存在するのはおかしい
Avatar
makeIteratorがある時点で一緒では
Avatar
let a: [Int] = [2, 3, 5] let b = a.lazy let c = b.flatMap { [$0, $0] } print(type(of: c)) LazyCollection<FlattenBidirectionalCollection<LazyMapBidirectionalCollection<Array<Int>, Array<Int>>>>
1:32 AM
これって @escaping じゃない SequenceflatMap 呼ぶのはどうすればいいんですっけ?
Avatar
as Arrayとかやればよさそう
Avatar
@nonescaping を クロージャの型に明示できないっけ
1:32 AM
@nonescaping@escaping に変換することはできないから自然といけそう
Avatar
let a: [Int] = [2, 3, 5] let b = a.lazy let c: [Int] = b.flatMap { [$0, $0] } print(type(of: c)) Array<Int>
1:35 AM
LazySequenceのこの手のメソッドが一通りSequence版とLazy版があって
1:35 AM
オーバーロード解決でSequence版を踏んだところでlazyになってた要素が巻き取られる
1:36 AM
というのが現状か
Avatar
そう
Avatar
@nonescaping を クロージャの型に明示できないっけ
できるっけ?やり方わからない・・・
Avatar
個人的には明示的にメソッド呼んでlazy解除がいいと思う
Avatar
「巻き取る」ことを明示的に「.asSequence」とかで変換するほうが
Avatar
そうそうそうそうそう
Avatar
ずっとlazyであることが確実になるね。
1:36 AM
まーたしかにどうせどこでSequenceになるかを意識して書かないといけないのだから
1:36 AM
明示的に変換させるほうがマシな気もするな。
Avatar
今の状態はぱっと見たときにどこからlazyじゃなくなったのかわからん (edited)
Avatar
これもまた暗黙のキャスト系の話しだな・・・
Avatar
てかね
1:37 AM
Sequence.Filteredとか高階型のMapped導入しても
Avatar
どうなんだろう今の状態じゃないと効率的じゃないパターンがあるのかも
Avatar
@escapingの有無が解決できない以上LazySequenceは完全にSequence protocolの上に乗ることが出来ない
Avatar
それはぱっと思いつかないけどなぁ < 効率的じゃないパターン
Avatar
あれ? @nonescaping なくなった?
Avatar
それは2までかな
Avatar
lazy → nonlazy 変換は現状で↓でできるから、 makeIterator を持った protocol を分離して( Iterable とか)、 LazySequenceProtocol はそれを継承して、 ArrayIterable を受けるイニシャライザを持てば OK そう。 let a: [Int] = [2, 3, 5] let b = a.lazy let c = Array(b) print(type(of: c))
Avatar
error: TempGround.playground:3:9: error: @escaping attribute may only be used in function parameter position var b: @escaping () -> Void = a ~^~~~~~~~~
1:40 AM
func f(a: @escaping () -> Void) {} var a: () -> Void = {} f(a: a)
1:40 AM
勝手に @escaping になっちゃうしローカル変数だと表明できないのか
Avatar
ローカル変数は無理でしょ
1:40 AM
変数に入った時点で @escaping では?
Avatar
その変数が他のescapingなクロージャから参照されるとかでエスケープしていないなら (edited)
1:41 AM
大丈夫そうだけど
1:41 AM
@nonescaping を クロージャの型に明示できないっけ
まあこれは無理でした
Avatar
もし↓こんなのできたら意味不明じゃない? func foo() -> @nonescaping () -> Int { return { 42 } }
Avatar
そこに書けたらおかしいですね。
Avatar
うーん、戻り値で返せないならローカル変数に書けても問題は起こらない?
Avatar
sharedinout は、ローカル変数には書けるようにする提案がありますよ
1:44 AM
その変数宣言以降の行を即時クロージャに包んで引数にそのmodifierをつけるのと
1:44 AM
実質的に同じだからです
1:44 AM
今は無理だけど。 (edited)
1:46 AM
func f() { var a: Int = 3 var refA: inout Int = a refA = 4 } ↑コレは今は無理だけどできていいよねって話で
1:46 AM
func f() { var a: Int = 3 func f2(refA: inout Int) { refA = 4 } f2(refA: &a) } ↑なぜならこれができちゃうからです
1:46 AM
同じような事が @escaping にも言えないかなと思っていた。
Avatar
nonescaping は引数にしか現れないけど(デフォルトだから修飾子はいらないけど)、↑の原理で言えばいけそうな気がするね。 (edited)
1:49 AM
でもそれって escaping と nonescaping のオーバーロードがあるときにしか役に立たなそう・・・
1:51 AM
escaping は nonescaping のサブタイプだから、 nonescaping への変換は問題にならないし、ローカル変数に代入されたクロージャでも実質的に nonescaping で良いものだったら最適化でインライン展開とかまでされそう。 escaping のオーバーロードがない限り。
Avatar
1:52 AM
nonescapingがescapingのサブタイプじゃないですかね?
1:52 AM
あれ?
Avatar
いや、あってると思う
Avatar
あかん、ねむすぐる
Avatar
escapingなものを nonescaping に渡せるけど逆は無理
Avatar
@tarunon US 時刻なんでしたっけ?w
Avatar
たしかにだからそもそもlazy版が呼べるシチュエーションでは通常版がどうせ呼べちゃうな。
Avatar
US時刻は問題ないんですが機内で寝てないので
1:53 AM
さながら徹マン明けで実験する大学生の状態です
Avatar
@tarunon たまたま目が覚めて夜中のツイートリアルタイムに見たんですが、ここで参加すると寝れなくなると思ってスルーしましたw
Avatar
US来て一番辛いの、ディスコにネタ投げたいのに現地時間午前4時で誰も反応しないところだ
Avatar
それ
Avatar
投げて1日待って
Avatar
それTwitterに書いたときは未だ遠慮する気持ちが微塵ほどはあったんですが、堪えきれなかった
Avatar
RxSwiftのcombineLatestはオリジナルなテンプレート言語を実装していた 簡単なテキスト処理で swift に変換してる。 https://github.com/ReactiveX/RxSwift/tree/master/Preprocessor https://github.com/ReactiveX/RxSwift/blob/master/Preprocessor/Preprocessor/main.swift#L69
RxSwift - Reactive Programming in Swift
RxSwift - Reactive Programming in Swift
Avatar
combineとzipは組み合わせになるからそうやね
Avatar
現状のジェネリクスの範疇で作れないから、生成はしてると思ってたけど、どんなツールでやってるかは調べてなかった。
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
7:06 AM
妥当な気がする。
3:04 AM
ボランティア募集らしい
To help with this, I am looking for 3-4 volunteers from the Swift community to create a workgroup to discuss and create a plan for the structure for the Discourse-based forums.
Avatar
https://github.com/apple/swift-corelibs-foundation/pull/1301 Foundation、swift-evolutionとは別のパブリックなプロポーザル制になったのかな? (edited)
Avatar
While we have no formal process at this time for proposals of changes to Foundation-only code, I would still like to post one that we have run through our internal process here for additional public comment. https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171106/040959.html
Avatar
なるほど、ありがとうございます!
Avatar
この後Foundation-onlyのプロポーザルプロセスの続報はあったのかな?
Avatar
2017 LLVM Developers’ Meeting: “Implementing Swift Generics ” https://youtu.be/ctS8FzqcRug @YouTubeさんから
11:33 PM
Slava pestovとJohn maccallがSwiftのジェネリックコードのコンパイルについて説明する動画 (edited)
11:34 PM
前半のSlavaが Value Witness Table で、後半のJohnが Protocol Witness Tableに言及してて、とてもよくわかる
🦆 2
11:34 PM
クロージャのthunk変換とかも出てくる
11:35 PM
2年前にこの動画が見たかったw
Avatar
コメントって範囲に対して書きたくなりませんか? /* ○○の処理 */ { foo() bar() baz() } みたいな。 (edited)
Avatar
なるけどできないからだいたいこうする // xxの処理 foo() bar() baz() // yyの処理 (↑の空行がxxの処理の終わり感を出す) (edited)
Avatar
do 使うのは?
1:34 AM
変数宣言絡むとあれですけど
Avatar
そうだね。いつも do で書いてる気がしてきた。
🙃 1
1:35 AM
↓みたいなの作ったらどうかと思ったけど正気を失ってた。 func *(lhs: String, rhs: () -> ()) { rhs() } "○○の処理" * { foo() bar() baz() }
Avatar
do にコメント統合できると文章的に理解できて良い気がする do something { ~~ }
Avatar
do /* これでいいのでは? */ { }
Avatar
処理: do { // ... }  も大抵はいけるw (edited)
Avatar
@omochimetaru それでいいですけど囲うの面倒でだいたい末尾に//で書いてます
Avatar
同じく do { // something } (edited)
1:39 AM
もしくは // ○○の処理 do { }
Avatar
実際 PREPARE: do { } PROCESS: do { } FINALIZE: do { } みたいなのはたまに使います。
Avatar
ラベルがあるとラベルジャンプを使うのでは?って読者が無駄に警戒してしまいませんかね
1:45 AM
二重returnぐらいでしか使わないからパット見みつからないし大丈夫かな
Avatar
なるほど、そういう心配か。抜けるには break PREPARE  などラベルを明示しないと抜けられない+ラベルくらいしか全大文字使わないので目立つ。ので問題無いと思っています。
Avatar
swiftのラベルはループ周りだけなんですかね? だとしたらdoについてるのは実質無意味として見られそう
Avatar
PREPARE: do { guard let foo = foo else { break PREPARE } } とか動きます。
Avatar
便利そうだな
1:50 AM
見落としてるだけでうまく使えるところがありそう
Avatar
dobreakできるんですか。 guardの中だけかな
Avatar
↑これとか、 while { switch { } } の形で、whileを抜けたいから ローカルfunc 作ってreturnしてるんだけど
1:52 AM
ラベルにできそうだ。
Avatar
guard じゃなくてもbreakできますよ。
Avatar
さっきコンパイル通らなかった気がしたんですが普通に実行できました
Avatar
ラベル break は Java とかでもある気がする。 // Java public class LabelBreak { public static void main(String[] args) { FOO: { System.out.println("A"); if (Math.random() < 0.5) { break FOO; } System.out.println("B"); } } }
Avatar
ちなみに、 continue で redo 的なこともできるんだけど、これが正式にサポートされているかは不明。 PREPARE: do { if !finished { continue PREPARE } }
Avatar
えっ、かっこいい
2:03 AM
一番下に書けばwhileもどきになりますね。
Avatar
パーサ書くとき等に便利な場面もあるんですけどね。 (edited)
Avatar
ありそう > パーサ
Avatar
gysb自分で使ってみたけどいい感じ テンプレート https://github.com/omochi/ReactiveEmitter/blob/master/Sources/ReactiveEmitter/Operator/Combine.swift.gysb 生成物 https://github.com/omochi/ReactiveEmitter/blob/master/Sources/ReactiveEmitter/Operator/Combine.swift gyb使ったときに比べてよかったのは
  • 静的チェック (変数名の typo が検出できた )
  • 三項演算子が便利 (例: ${ i < n-1 ? ",": "" })
ReactiveEmitter - Lightweight observable in Swift seen from EventEmitter in JavaScript.
ReactiveEmitter - Lightweight observable in Swift seen from EventEmitter in JavaScript.
👍 1
3:28 AM
  • joinedが [String] のメソッド (pythonだと separator.join([s0, s1, s2])
Avatar
RangeReplacableCollectionのreplaceSubrangeメソッドが、レンジとして RangeExpression というプロトコルを渡すようになっていた https://developer.apple.com/documentation/swift/rangeexpression
2:08 PM
{Countable}{Closed}Range の4種類がこれを満たしていて
2:09 PM
RangeExpression.relative(Collection) で Range に変換できるみたいで
2:09 PM
@koher のよく言ってる4種類のレンジのオーバーロードの話って、これで解決する?
2:10 PM
https://developer.apple.com/documentation/swift/rangereplaceablecollection/2853454-replacesubrange ドキュメントだと Range<Index> を取っていて、 RangeExpression になってないのだけど。
2:12 PM
同時にもう一個気になった事があって、 Protocol Extensionで提供されたメソッドが mutating のとき、conformしてる型がclassだと、 var でないとメソッドが呼び出せない。 自分でconformするときは nonmutating func でconformできるのに。 このおかげで、本当は replaceSubrange だけ実装すればいい場面で、 append やら、なにもかも、デフォルト実装の恩恵がうけられない。
Avatar
ReactiveEmitter - Lightweight observable in Swift seen from EventEmitter in JavaScript.
ReactiveEmitter - Lightweight observable in Swift seen from EventEmitter in JavaScript.
Avatar
public protocol RangeReplaceableCollectionClass : class, RangeReplaceableCollection {} にしたかったって事?
Avatar
そうですね。appendとかを、RangeReplaceableCollectionのデフォルト実装で済ませたかった。
Avatar
なるほど。
4:53 AM
where self: immutable みたいなのが欲しくなるね
Avatar
mutatingだけじゃなくて、initの制約もあるから、今回の目的だとそれだけでもダメそうでした
4:57 AM
initでプロパティの実体を参照して、変更時にイベントを流そうとしてるけど、 プロパティの実体を受け取らないinitを持たなきゃいけないので、
4:58 AM
あくまで様々な変更操作を自動定義する部分だけ欲しかった
Avatar
RxDataSorcesに、自身を引数に取るinitをrequiredにすることで、擬似的にmutableっぽい挙動を実現させてる実装があるからワンチャン参考になるかも (edited)
Avatar
なるほど。後でみてみる
Avatar
[swift-evolution] Python Interop with Swift 4+ by Chris Lattner https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171113/041463.html (edited)
Avatar
PyTuple_New とかなんで使えるのかと思ったら
2:28 AM
冒頭で import Python してますね
2:28 AM
そもそもそんなパッケージがOSX SDKに入ってるのしらんかった。
2:29 AM
let d = np.call(member: "array", args: Python.array(6, 7, 8), kwargs: [("dtype", "i2")]) proposalが通れば↑の呼び出しがSwiftの通常関数呼び出しのように書けると (edited)
Avatar
import Python ってどこ?
2:30 AM
ああ
2:31 AM
PythonGlue
Avatar
PythonInterop.playground/Source/PythonGlue.swift
Avatar
/System/Library/Frameworks/Python.framework
Avatar
同じとこにRuby.frameworkなんてのもある
Avatar
ヘッダーを見ればいいのか
2:36 AM
Jump to Definition うまくいかないけど、 Swift で展開されたインタフェースがみたい・・・
Avatar
Playgroundで import Python って書いたら飛べました
2:37 AM
iOSじゃなくてMacOS Playgroundにして。
Avatar
お、できた
Avatar
いきなりPythonGlue.swiftを開くのではなく、PythonTutorialの中でPython.importとかからJump to Definitionした先から行くとひらけます。 (edited)
🙏 1
Avatar
なるほど
2:41 AM
ARC 化してる・・・ public init(borrowed: UnsafeMutablePointer<PyObject>) { state = borrowed Py_IncRef(state) } public init?(borrowedNullable: UnsafeMutablePointer<PyObject>?) { if let borrowed = borrowedNullable { state = borrowed Py_IncRef(state) } else { return nil } } public convenience init(python: PyVal) { self.init(owned: python.ownedPyObject) } deinit { Py_DecRef(state) }
2:41 AM
owned と borrowed と区別してるのか
2:42 AM
もうちょっと上があった。 public final class PyRef : PyVal { private var state : OwnedPyObject public init(owned: OwnedPyObject) { state = owned } public init?(ownedNullable: OwnedPyObject?) { if let owned = ownedNullable { state = owned } else { return nil } } public init(borrowed: UnsafeMutablePointer<PyObject>) { state = borrowed Py_IncRef(state) } public init?(borrowedNullable: UnsafeMutablePointer<PyObject>?) { if let borrowed = borrowedNullable { state = borrowed Py_IncRef(state) } else { return nil } } public convenience init(python: PyVal) { self.init(owned: python.ownedPyObject) } deinit { Py_DecRef(state) } public var borrowedPyObject : UnsafeMutablePointer<PyObject> { return state } public var ownedPyObject : OwnedPyObject { Py_IncRef(state) return state } }
Avatar
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...
7:30 AM
この PR で、 Generic Manifesto に 「Generic assciated types」の節が追加されるんですが
7:30 AM
+Associatedtypes could be allowed to carry generic parameters. + +Swift +protocol Wrapper { + associatedtype Wrapped<T> + + func wrap<T>(_ t: T) -> Wrapped<T> +} + +Generic associatedtypes would support all constraints supported by the language including where clauses. + +Note: generic associatedtypes address many use cases also addressed by [higher-kinded types](#higher-kinded-types) but with lower implementation complexity. (edited)
7:32 AM
備考: generic associatedtypes は 高階型 で取り扱う(address) 多くのユースケースを取り扱う (edited)
7:32 AM
って書いてあって気になる。
Avatar
これ高階型とどこが違うのな
7:39 AM
ぱっと見理解できない
Avatar
俺も Swift の protocol が 高階型と違う点を自分なりに考えた時、 ジェネリックな型 F<T> を名前 X で受けた時に、 X を F と T でばらして扱えるかどうかだと思って
7:40 AM
この定義なら Wrapped<T> , Wrapped , T でバラせる から同等な能力な気がする
Avatar
これ使ってモナドプロトコルってどうやれば作れる?↓とか? protocol Monad { associatedtype Value associatedtype Generated<T>: Self where T == Value func flatMap<T>(_ transform: (Value) -> Generated<T>) -> Generated<T> }
Avatar
あー、 Self から ガワのモナドだけ取得する必要がありますね
Avatar
Haskell では flatMap だけ抜き出すと↓。 class Monad m where (>>=) :: m a -> (a -> m b) -> m b
9:01 AM
Functor class Functor f where fmap :: (a -> b) -> f a -> f b
Avatar
koher の例だと Optional<T> : Monad をみたそうとすると、 T -> U の flatMap で Generated<U> : Optional<T> って制約になっちゃってできなそう?
👀 1
Avatar
今の Swift の Self って特殊すぎると思う。
Avatar
Haskell class Eq a where (==) :: a -> a -> Bool class Monad m where (>>=) :: m a -> (a -> m b) -> m b (edited)
9:15 AM
Swift protocol Equatable { static func ==(lhs: Self, rhs: Self) -> Bool } protocol Monad { ??? // どんな記法が馴染む? }
9:20 AM
つまり、 Haskell では( Swift の言葉で言うと)プロトコルを一度別の記号 am に読み替えているから自然に書けるけど、 Swift ではそれを Self で表しているのでジェネリックにしたときにどう書いていいのか。 Self が Haskell の Monadm じゃなくて m a を表してしまっているので m b をうまく書けない・・・。
Avatar
Monadは表現できないっぽいですね、あくまでArrayかLazyかを明記するためのものに感じる
Avatar
protocol A { associatedtype E } protocol B { associatedtype E } struct C: A, B { typealias A.E = Int typealias B.E = String } これはムリ。困った。仕様?実装上の都合?
Avatar
例のごとく深い意図があるのかたまたまそうなのかわからない系やな・・・ ドキュメントで明確に言及してるものを見た記憶は無し
Avatar
@tarunon AとBにそれぞれのEを返すメソッドなりプロパティなりがあって、typealiasを省略できる書き方にしたらどう?
Avatar
駄目です
Avatar
だめかあ
Avatar
これに関しては考えつく限り全てのワークアラウンド試して全滅しました
3:34 AM
因みにさっきのひらりの例は、ambitiousと出てコンパイルエラーになる気がします
Avatar
ambiguous
Avatar
EをAとBそれぞれのメソッドから型が推論出来るが制約レベルが同一なため決定できない→ambitious
3:36 AM
これ困ってる理由は、ObserverとObservableTypeで
Avatar
ambitious なコンパイルエラーw
3:36 AM
大志を抱いてる
Avatar
Eの型を変換させながらバイパスしたいときに、ObserverTypeとObservableTypeを準拠できないんですよ
Avatar
アンビシャス
Avatar
あw
Avatar
Avatar
綴りが悲しいことに
3:38 AM
まあ良いや通じるっしょ
Avatar
ww
Avatar
@rintaro こういうのってどうやって検索してるんですか?
Avatar
すでに投稿されてるんですね、スレ読んでみる
Avatar
This kind of disambiguation has been discussed on the Swift evolution list a few times, but no single proposal has gotten traction yet.
Avatar
@koher ですです。今回は "associatedtype same name"
Avatar
なるほど。ありがとうございます!🙏
Avatar
残念ながら仕様だしMLにも過去に出てきたと
Avatar
コンパイラコミッターならではの知識データベースができあがってるのかと思ってました💦
Avatar
SR-3329自体はConditionalConformanceが来れば何かしらのカタチで落ち着きそうだ
Avatar
https://github.com/github/swift-style-guide 気づいたらGitHubのSwift Style Guideがアーカイブされちゃったけどなんでだろ
swift-style-guide - Archived Style guide & coding conventions for Swift projects
8:26 PM
誰も触らないからサヨナラということらしい
8:30 PM
ConditionalConformance以降、 extension Array: MyProtocol ってやった場合って、Array全てがextension持つ(暗黙的にArray<Any>ではない)ってことになるのかしら
8:31 PM
あー
8:32 PM
extension Array: MyProtocol where Element: Any こう解釈出来ますね、そして全てOKになる
Avatar
↓がやけに長い associatedtype 名になってるのって、この前話した衝突回避のためなのかな? protocol DynamicCallable { associatedtype DynamicCallableArgument associatedtype DynamicCallableResult func dynamicCall(arguments: [DynamicCallableArgument]) throws -> DynamicCallableResult } https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d
1:44 AM
この DynamicCollable 、 Python の import に限らず純粋に Swift の範囲でも使えそう。これまで何度か値を callable にしたくなったことがあった気がする。 Codable のときもそうだったけど、 JSON のデコード楽にしたい→汎用的な仕組みを導入の流れ、いい。
1:44 AM
ただ、引数が [DynamicCallableArgument] は動的型付け言語にひっぱられすぎな気も?
Avatar
Swiftの範囲で使うと型が死にますよ
Avatar
↓じゃダメだったのかな? protocol DynamicCallable { associatedtype DynamicCallableArguments associatedtype DynamicCallableResult func dynamicCall(arguments: DynamicCallableArguments) throws -> DynamicCallableResult } (edited)
Avatar
それだとPyValのときどうなります?
1:46 AM
引数を構築するラッパーが毎回必要になりそう。
Avatar
typealias DynamicCallableArguments = [PyVal] じゃダメ?
Avatar
pythonはラベルごとに渡せるから
1:47 AM
配列ではダメですね
Avatar
じゃあ typealias DynamicCallableArguments = [String: PyVal] は?
1:48 AM
typealias DynamicCallableArguments = [(String, PyVal)] でもいいけど。
Avatar
そうすると、呼び出しのときに毎回辞書作る感じになりますよね
1:49 AM
swiftのラベルつき呼び出しをシームレスに渡したくてそうなってるみたいです
Avatar
typealias DynamicCallableArguments = [(String, PyVal)] なら変わらないのでは?
Avatar
長いassoc名はそうですね、スコープになったほうがよさそう
1:51 AM
今の提案は
1:51 AM
obj.method(a: 1, b: 2)
1:52 AM
って書くと、 [(“a”, 2), (“b”, 3)]が dynamicCallに渡る
1:54 AM
あれ?さっきのちょっと違うな ~ protocol DynamicCallable { associatedtype DynamicCallableArgument associatedtype DynamicCallableResult func dynamicCall(arguments: [(String, DynamicCallableArgument)]) throws -> DynamicCallableResult } ~ (edited)
1:57 AM
[swift-evolution] [Pitch] Introduce user-defined dynamically "callable" types
1:57 AM
このメールに書いてあるやつです
1:57 AM
途中で変わったのかな
1:59 AM
protocol DynamicCallableWithKeywordsToo : DynamicCallable { func dynamicCall(arguments: [(String, DynamicCallableArgument)]) throws -> DynamicCallableResult }
Avatar
[swift-evolution] [Pitch #2] Introduce user-defined dynamically "callable" types
の方を見てる。
Avatar
新しい提案で型が分割されていたのですね https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d
Avatar
古い方追ってなかったからどういう議論があって変わったのかは知らない。
2:03 AM
うーん、これは Callable にするものというより、純粋に DynamicCallable と捉えた方がいいのか。
2:03 AM
それなら当然型はないし N 個の引数でも当たり前か。
Avatar
新しい方でも配列の要素の型が単一化されちゃうから
2:04 AM
一般のCallableには遠いですね
Avatar
あまりにもざっくりとしか読んでなかった。
Avatar
なんか、色々すっ飛ばして、パイソンバインディングしよう!ってのがまず考えられてて
2:05 AM
それでスレも若干荒れてました
2:08 AM
JavaScriptはラベルつきが無かったはずだから前者だけやればいいのかな
Avatar
#beginner-help-archived のやつ、 #ifelse if 消すことができなかったから、コードの重複を消すために gyb で制御して #if を生成するという闇コードに・・・。 extension Image where Pixel == ${pixel_type} { public init(uiImage: UIImage) { % for core_image_available in [True, False]: % if core_image_available: #if os(iOS) || os(tvOS) % else: #else % end if let cgImage = uiImage.cgImage { self.init(cgImage: cgImage) % if core_image_available: } else if let ciImage = uiImage.ciImage { let context = CIContext() // This `guard` can be replaced with `!` if you are sure that the `createCGImage` below never fails. guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else { fatalError("Failed to create a `CGImage` from an internal `CIImage` object from this `UIImage` instance: \(uiImage)") } self.init(cgImage: cgImage) % end } else { // This `gurad` can be replaced with `assert` if you are sure that the `size` is always equal to `.zero`. guard uiImage.size == .zero else { % if core_image_available: fatalError("The `size` of this `UIImage` instance (\(uiImage)) is not equal to `.zero` though both `cgImage` and `ciImage` of the instance are `nil`.") % else: fatalError("The `size` of this `UIImage` instance (\(uiImage)) is not equal to `.zero` though `cgImage` of the instance is `nil`.") % end } self.init(width: 0, height: 0, pixels: []) } % if not core_image_available: #endif % end % end }
Avatar
メソッドでラップすれば良いのでは。
Avatar
init なので切り出すのが微妙なのと(できなくはないですが、 UIImage が特定条件のときだけ呼ばれる private init は可読性低そうなので)、たとえ切り出しても条件分岐のコード自体は多重になってしまうんですよねぇ。
Avatar
init でしか呼べないメソッドみたいな仕組み欲しいですよね、イニシャライズが複雑になりがちなclassに
Avatar
stored propertyを全部タプルで固めてstatic funcで取り回せば、なんとかなることがあるよ
4:24 AM
self.initだと制約がキツくてなんともならないことがままある
Avatar
class以下の要素について複雑さをひとまとまり毎に型を作ってそれぞれのinitで表現すればいいんじゃないの
Avatar
今やりたいのは↓なので init(uiImage: UIImage) { if let cgImage = uiImage.cgImage { self.init(cgImage: cgImage) } else if let ciImage = uiImage.ciImage { ... self.init(...) } else { guard uiImage.size == .zero else { fatalError(...) } self.init(width: 0, height: 0, pixels: []) } }
4:28 AM
この } else if let ciImage = uiImage.ciImage { ... self.init(...) の部分が watchOS では CoreImage が使えない関係でエラーになってしまうので除去したいけど #if でここだけ除去できないので
4:31 AM
共通部分をくくりだすにしても
  • イニシャライズはしないといけないのでメソッドにはできない
  • 例えば else { } の中イニシャライザにしようとすると型で区別できない→特殊なラベル名を持ったイニシャライザを作ることになるけど、 UIImage がサイズ .zero のときにしか呼んではいけないとかわかりづらすぎる
  • その側の if/else if/else の条件分岐の条件は括り出しようがない
のでコードジェネレーションで共通化しました。
Avatar
@koher watchOSの場合だけ UIImageciImage メソッドをextensionで足すのはどうですか?実装としてはnilを返すだけにしておく。 (edited)
👍 2
Avatar
privateextension にするのか。それはありかも。
Avatar
nil返すだけExtension割とやる
Avatar
下側のレイヤーで吸収する
4:32 AM
上側だとこのように制御が絡んでつらい
4:33 AM
ちょうど最近 @ikesyo も同じようなアレをextensionを併用して畳み込んでました
Avatar
CIImageという型自体が存在しない場合は、適当な偽の型を作って吸収できるかな?
4:34 AM
typealias CIImage = Never とか
Avatar
空のclass定義しちゃえばええと思う
Avatar
空のclassだとinitできちゃうからNever aliasの方が良くないかな
Avatar
Neverつかうとこの行実行されないっすよのwarningいっぱい出ない?
Avatar
あーそれうざいね
Avatar
CIImage だけじゃなく CIContext も作ることに・・・
Avatar
引数にNeverを取るinitだけ生やせば生成されないことは保証できるからそれが良いかな?空enumはオレオレで作れたっけ
Avatar
空のclassだとinitできちゃう
initを @available で潰そう
Avatar
やるやる
Avatar
まあ private なのでそこはいいかと。
Avatar
空enum作れるからそれが一番良さそう
Avatar
それNeverとして働くんじゃないっけ
Avatar
警告は出ないNever
Avatar
Never として働くはず。
Avatar
で使えるんじゃ
4:38 AM
あれ、出るのか
Avatar
警告出ないんですっけ?
4:38 AM
記憶が定かでない・・・
Avatar
空enum=Neverなの
4:39 AM
知らなかった…
Avatar
出ないっぽい
4:39 AM
空enum、偽型とかネームスペースにも使えて便利だ
4:40 AM
そういえば最近ネストprotocolのevolution上がってた気がする(タイトルだけ見た)
Avatar
空enumを返すメソッド、guardの中から離脱するやつとしても使えるってこと?
Avatar
@hiragram Never のような振る舞いはするけど型としては別です。 1> enum Nothing {} 2> Nothing.self == Never.self $R0: Bool = false 3> Never.self == Never.self $R1: Bool = true
Avatar
ふむ
Avatar
コンパイラの諸々の加護もないから警告も出ないよ
Avatar
空enum便利そう
Avatar
guard let hoge = fuga else { piyo() // <- 空enumを返すメソッド } これコンパイル通るん
Avatar
4> func foo() -> Nothing { 5. fatalError() 6. } 7> guard false else { 8. foo() // OK 9. }
Avatar
うおーまじか
Avatar
今回の件に関してだと、 enum だと : AnyObject を満たさないので、 CIImage: AnyObject であることに依存したジェネリックなメソッドが他にあったりするとうまくいかないかなと思ってた
Avatar
局所的に使うだけだから空 enum でもいいかも
Avatar
CIImageってAnyObjectだっけ?
Avatar
まあ、初期化部分だけの問題だから他のメソッドは全部 #if で消せば大丈夫かな
4:43 AM
@tarunon ObjCのオブジェクトは全部そうなんじゃないか
Avatar
うおクラスだ
Avatar
局所的に使うだけだから空 enum でもいいかも
現実的にはそうかも
Avatar
open class CIImage : NSObject, NSSecureCoding, NSCopying {
4:44 AM
CFStringとかCGImageもclassなんすね
4:44 AM
めっちゃstructだと思いこんでた
Avatar
てかそうじゃないといろいろ無理じゃない?
4:45 AM
もともとObjC側でクラスインスタンスとして振る舞ってretain/releaseされるやつらだから。
Avatar
Obj-Cだからね
Avatar
Data とかは Swift側で明示的に定義された struct で、内部で class NSData を保持するだけのCOWだよ
Avatar
CoreGraphicsとかCoreImageとかUIKitとかいつになったら完全にSwift化されるんだろうな…(遠い目
Avatar
なぜか as NSData できるから一見 toll free だけど 中のフィールドが飛び出してくるだけ
Avatar
enumにNSObjectProtocolをconformさせようとすると失敗する話
4:46 AM
NSObjectProtocolの定義はclassって書いてないのにclassじゃないとコンパイル通らないの感情が厳しい
Avatar
CGImage 等に限らず、他の言語でも大抵は画像の型を作ろうとすると参照型になってしまうので、 Swift の特性を活かして値型の画像型作ったらおもしろそうという意味もあり EasyImagy 作ってます。
Avatar
@objc enumで書かないとダメかな?
Avatar
実際には暗黙的にclass強制なのでどうやってもダメッポ
Avatar
@lovee それってむしろ Int になりそう?
4:48 AM
associated value つけられなくなったような
Avatar
ダメだった😇
4:53 AM
https://developer.apple.com/documentation/objectivec/1418956-nsobject?language=objc 公式ドキュメント読んだらそもそもNSObjectってObj-Cではプロトコルで定義されてそれがSwiftにはNSObjectProtocolとしてブリッジされてるだけのようで…😇
Avatar
public init(uiImage: UIImage) { func cgimage(from uiimage: UIImage) -> CGImage? { #if os(iOS) || os(tvOS) return uiimage.cgImage ?? { guard let ciImage = uiImage.ciImage else { return nil } let context = CIContext() guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else { fatalError("Failed to create a `CGImage` from an internal `CIImage` object from this `UIImage` instance: \(uiImage)") } return cgImage }() #else return uiimage.cgImage #endif } if let cgImage = cgimage(from: uiImage) { self.init(cgImage: cgImage) } else { // This `gurad` can be replaced with `assert` if you are sure that the `size` is always equal to `.zero`. guard uiImage.size == .zero else { fatalError("The `size` of this `UIImage` instance (\(uiImage)) is not equal to `.zero` though both `cgImage` and `ciImage` of the instance are `nil`.") } self.init(width: 0, height: 0, pixels: []) } } (edited)
Avatar
ここまでくると結構読みにくいですよねイニシャライザ
Avatar
gyb使うよりはマシな気がしますよ。
Avatar
gyb は別の理由で元々使ってるので💦
Avatar
なるほど、複数登場するのですね。
Avatar
登場箇所は1回だけどそれがgybの中だから
4:57 AM
.swiftとしては何回も出てきている?
Avatar
なるほど、複数登場するのですね。
そうなんです。 Conditional Conformance が導入されれば gyb 消せるところもありそうですが・・・。
4:59 AM
登場箇所は1回だけどそれがgybの中だから .swiftとしては何回も出てきている?
extension は .swift でも 1 回だけど、それを使うコードを複数回です。
👀 1
Avatar
4.1でconditional conformanceちゃんとリリースされそうな流れですね。標準ライブラリ側も込みで。 https://github.com/apple/swift-evolution/pull/769
As discussed in this thread, amend SE-0143: Conditional conformances to include the adoption of conditional conformances for Equatable by Optional, Array, and Dictionary. Implementation available a...
🎉 3
Avatar
スケジュールもそれに合わせてきてる感じ [swift-dev] Final re-branch for Swift 4.1 pushed out to December 4 https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20171127/006036.html (edited)
Avatar
なるほど。感謝祭からちょっと後の方が確かに良い気もする。
Avatar
Conditional Conformance に関連して CountableRange 等の廃止の話を見た記憶がないんですが、それはされないんでしょうか?
Avatar
詳しく見てないですが、それくらい大きい変更はSwift 5になるのではと勝手に思っています (edited)
Avatar
ソース互換性はなくなっちゃいますもんねぇ。 typealias を作っておけば大丈夫なのかな・・・。
Avatar
RangeExpressionでオーバーロード4重化は回避されてるけど、CCを使ってそれ無しに同じことができるんですか?
1:14 AM
いまはPartial系があるから4重じゃなくて、いくつあるんや・・・
Avatar
@omochimetaru RangeExpression は必要なんじゃないかな?でも Countable 系は Conditional Conformance があれば不要なはず。
Avatar
Indexの型でRangeの条件付き系になるのか
Avatar
うん
Avatar
protocol P { var p: Int { get } } extension P where Self: A { var p: Int { return self.p * 2 } } class A {} extension A: P {} let instance = A() print(instance.p)
12:40 AM
これ、コンパイルエラー出せないんですかね
Avatar
classだけでも自身のプロパティ参照してループ作れる
Avatar
なるほど・・・
Avatar
最終的に結果が出るループと出ないループの区別が難しい、みたいな話を聞いた気がします
12:42 AM
pとq作ってお互いに参照したらそれもループだけど
12:43 AM
この手のやつ判定しようとするとO(2^フィールドの数)になるんじゃないかな
12:44 AM
単純なやつでも、サブクラスまで見ないといけないというのもあるから難しいかも。
Avatar
う〜んたしかにpだけでも再帰で収束させられるし仕方ないのか
Avatar
プログラムが停止するかどうかを一般的に判定するプログラムを作ることはできません(数学的に証明されています)。 特定の問題について考えても、ちょっとしたプログラムでも停止するかどうかを考えるのはとても難しいです。たとえば、↓のプログラムが停止するかを効率的に判定できるプログラムを書けるなら、それでフェルマーの最終定理が解けてしまいます。 outer: for i in 3... { for n in 3...i { for x in 1...i { for y in 1...i { for z in 1...i { if x ** n + y ** n == z ** n { break outer } } } } } }
Avatar
なるほど、ありがとうございます
Avatar
omochimetaru 12/1/2017 2:11 AM
let yPlaneBuffer = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0) yPlaneData.withUnsafeBytes { (data) in yPlaneBuffer!.copyBytes(from: data, count: yPlaneData.count) }
2:11 AM
これコンパイル通るのなんでだろう
2:12 AM
yPlaneDataData 型で、 withUnsafeBytes は public func withUnsafeBytes<ResultType, ContentType>(_ body: (UnsafePointer<ContentType>) throws -> ResultType) rethrows -> ResultType
2:12 AM
で、copyBytes public func copyBytes(from source: UnsafeRawPointer, count: Int)
2:12 AM
だから
2:12 AM
クロージャの (data) の推論が
2:13 AM
UnsafePointer<ContentType>UnsafeRawPointer でぶつかって解決できないように思う
Avatar
norio_nomura 12/1/2017 2:16 AM
https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-ID146 When a function is declared as taking an UnsafeRawPointer argument, it can accept the same operands as UnsafePointer<Type> for any type Type. (edited)
Avatar
omochimetaru 12/1/2017 2:17 AM
なるほど、じゃあ、 引数渡すときに UnsafePointer< XXX > は UnsafeRawPointerに暗黙キャストできる
2:17 AM
具体的に XXX は何にになっているんでしょ・・・
Avatar
UnsafePointer<()> になっているっぽいです。
Avatar
omochimetaru 12/1/2017 2:24 AM
マジか・・・
2:24 AM
/Users/omochi/work/playground/MacGround.playground:1:8: UnsafePointer<Void> has been replaced by UnsafeRawPointer
2:24 AM
いまって UnsafePointer<Void> つかうとワーニングでるのに。
2:24 AM
それってどうやってわかりました? > なっている型
Avatar
norio_nomura 12/1/2017 2:25 AM
PlaygroundのQuick Help Inspectorで見えますね。
Avatar
omochimetaru 12/1/2017 2:25 AM
お。アプリの方でやってたけど、No Quick Help になってました。
Avatar
closureのパラメータじゃなくて、copyBytes(from:count:) に渡しているほうの data だと出ません?
Avatar
omochimetaru 12/1/2017 2:27 AM
おお!!
2:27 AM
出ました。なるほどーありがとうございます。
2:27 AM
どっちでも同じ結果になるとおもいこんでいました
Avatar
closure パラメータの Quick Help が出ないのはバグっぽいですよねー。
Avatar
omochimetaru 12/1/2017 2:28 AM
なるほど
2:28 AM
なんか結構、なんだ出ないやんけってスルーしてる事があるきがするけど
2:28 AM
使ってるところでやってみるのがよかったのか。 (edited)
Avatar
https://bugreport.apple.com お願いします><
Avatar
omochimetaru 12/1/2017 2:30 AM
どっちがいいんでしょう
2:30 AM
bugs.swift.orgと
Avatar
norio_nomura 12/1/2017 2:32 AM
SourceKitレベルで情報を取れない事が確認できるならば bugs.swift.org がいいのでは。確認できないなら bugreport.apple.com かな?
👍 1
Avatar
omochimetaru 12/1/2017 2:33 AM
あ〜なるほど・・・そういうふうに動いているのか
2:34 AM
あとで報告しておきます
Avatar
ちなみに、typecheck 結果の確認は -dump-ast でも出来ますよ。
Avatar
norio_nomura 12/1/2017 2:38 AM
SOURCEKIT_LOGGING=3 /Applications/Xcode.app/Contents/MacOS/Xcode でログをみた感じでは、SourceKitが返した情報をXcodeが表示していないだけぽい。
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
3:22 AM
もし引っかかると場合によってはマイグレーション不可案件なので、お知らせまで。
Avatar
structでモジュールを跨いでオレオレinitを作れなくなる?
Avatar
はい、4.1でワーニング出るようになると思います。
Avatar
norio_nomura 12/1/2017 4:00 AM
masterにはマージされてるけど、含んだスナップショットはまだ出てないのね。 https://github.com/apple/swift/commit/8f8f00012a391b7c254e2056ef382c768ca7671a
…ct-initializers-2 Implementation of SE-0189 "Restrict cross-module struct initializers to be delegating" rdar://problem/34777878
Avatar
Swift で書けるメタプログラミング向けのテンプレートエンジン gysb を作った - Qiita https://qiita.com/omochimetaru/items/422ddd04e95c55dd3833

メタプログラミングとテンプレートエンジン

プログラミングにおいて、そのプログラミング言語の機能だけではプログラムを書くのが大変だったり難しいときに、外部のツールなどを用いて、「プログラムを出力するプログラム」を作成して対応するこ...
Avatar
昨日のXcodeがクラッシュしたコード、
1:51 AM
多分、Playgroundに貼るとクラッシュ
1:51 AM
ですね、Swiftのバージョンは関係なかった
Avatar
ううむ、どうも再現しないんですよねー
Avatar
むむむ
Avatar
init(throws x: String) throws { // この中でOptionalなsuper.init(convenienceでself.init)を呼んでnilならErrorを出したい } ↑protocolワークアラウンド無しで解決する方法が欲しい
Avatar
ベースが自前クラスならそっちもfailableじゃなくて throws にすべきでは?と思いますね
Avatar
なんだっけ
5:48 AM
これ困ったのNSURLだった気がする
5:48 AM
NSURL(string: String) これをthrowsにしたい、できないおわた
Avatar
じゃあだめだー
Avatar
という感じ
5:48 AM
でも今はstruct URLになって困らなくなりました。
5:48 AM
UIImageで未だ困ることがある
Avatar
protocolワークアラウンドって例のself代入ですか
Avatar
そうです
5:49 AM
一旦optional initを適当な変数に受けてguard unwrap throwsしてselfに代入
Avatar
まぁそれしかないですよね。
Avatar
class Child: Base { init(b: String) throws { super.init(a: b) ?? { throw NSError() }() } } ↑こういうのやりたいですね
Avatar
そり
Avatar
無理やりだけどこういうのはどうですかね? class Child: Base { static func `init`(b: String) throws -> Child { guard let child = Child(a: b) else { throw NSError() } return child } }
Avatar
えっとそれは厳密にはinitではない
Avatar
それってChild(b: "") で呼べるんですかね
Avatar
返り値の型がSelfにならないので
Avatar
まあ見た目上では()
6:14 AM
それってChild(b: "") で呼べるんですかね
それが呼べるんですよ
👀 1
Avatar
Childの更にサブクラスを使うと崩壊です。 (edited)
👍 1
Avatar
呼べるのか……
Avatar
あ、throwsがあると呼べないっぽい?
Avatar
protocol workaroundだとSelf型でいけるんですが、あれはあれでまぁoptional initがrequiredでないと死亡とか結局詰んでる気はする
Avatar
4.1-dev は今日 master から最終 re-branch されたので、今はほとんど master と同じです。
Avatar
omochimetaru 12/5/2017 8:26 AM
ほう
Avatar
This post describes the goals, release process, and estimated schedule for Swift 4.1.
Avatar
omochimetaru 12/5/2017 8:28 AM
なるほど > December 4, 2017 (final branching)
Avatar
いまフラグ無しでcond conf使えるってことはやっぱ入れることになった可能性もあるかも?
Avatar
それっぽいPRは無さそうな気がする
😢 1
Avatar
omochimetaru 12/5/2017 9:23 AM
[omochi@omochi-iMac swhash]$ cat b.swift struct Box<T> { let value: T } extension Box: Equatable where T: Equatable { static func == (lhs: Box, rhs: Box) -> Bool { return lhs.value == rhs.value } } [omochi@omochi-iMac swhash]$ swift --version Apple Swift version 4.1-dev (LLVM c698959a5c, Clang dff0a814ae, Swift 9fef06e59c) Target: x86_64-apple-darwin16.7.0 [omochi@omochi-iMac swhash]$ swift b.swift b.swift:6:1: error: conditional conformance of 'Box<T>' to 'Equatable' depends on an experimental feature (SE-0143) extension Box: Equatable where T: Equatable { ^ [omochi@omochi-iMac swhash]$ swift -enable-experimental-conditional-conformances b.swift [omochi@omochi-iMac swhash]$ echo $TOOLCHAINS org.swift.3020171204a
9:24 AM
やっぱりオプション入れないとダメでした 12/04版
9:25 AM
Hashableの生成について
9:25 AM
@_transparent public // @testable func _mixForSynthesizedHashValue(_ oldValue: Int, _ nextValue: Int) -> Int { return 31 &* oldValue &+ nextValue }
9:25 AM
31倍しながら足すようになってた。
Avatar
structは31倍しながら足せばOKなのはわかる
9:26 AM
enumってどうなるかわかります?
Avatar
omochimetaru 12/5/2017 9:27 AM
enumは多分case番号を最初に混ぜ込むんじゃないかなあ
9:29 AM
enum Zoo : Hashable { case cat(Cat) case dog(String) }
9:29 AM
// Zoo.hashValue.getter sil hidden @_T01a3ZooO9hashValueSivg : $@convention(method) (@guaranteed Zoo) -> Int { // %0 // users: %4, %3, %1 bb0(%0 : $Zoo): debug_value %0 : $Zoo, let, name "self", argno 1 // id: %1 %2 = alloc_stack $Int, var, name "result" // users: %131, %126, %88, %85, %75, %72, %63, %25, %22, %12, %9, %134 retain_value %0 : $Zoo // id: %3 switch_enum %0 : $Zoo, case #Zoo.cat!enumelt.1: bb1, case #Zoo.dog!enumelt.1: bb6 // id: %4
Avatar
かっくん 12/5/2017 9:29 AM
9:29 AM
Avatar
other-swift flagsに何か入れてません?
Avatar
かっくん 12/5/2017 9:30 AM
🙄 1
Avatar
omochimetaru 12/5/2017 9:31 AM
// %5 // users: %66, %15, %6 bb1(%5 : $Cat): // Preds: bb0 debug_value %5 : $Cat, let, name "a0" // id: %6 %7 = integer_literal $Builtin.Int64, 0 // user: %8 %8 = struct $Int (%7 : $Builtin.Int64) // user: %10 %9 = begin_access [modify] [static] %2 : $*Int // users: %10, %11 store %8 to %9 : $*Int // id: %10 end_access %9 : $*Int // id: %11 // %68 // users: %129, %78, %69 bb6(%68 : $String): // Preds: bb0 debug_value %68 : $String, let, name "a0" // id: %69 %70 = integer_literal $Builtin.Int64, 1 // user: %71 %71 = struct $Int (%70 : $Builtin.Int64) // user: %73 %72 = begin_access [modify] [static] %2 : $*Int // users: %73, %74 store %71 to %72 : $*Int // id: %73 end_access %72 : $*Int // id: %74 %75 = begin_access [read] [static] %2 : $*Int // user: %76 end_access %75 : $*Int // id: %76
9:32 AM
ちゃんと追ってないけど冒頭で分岐したジャンプ先に0と1がそれぞれあるからこれな気がする
9:33 AM
6ケースまで増やしたらこの箇所が2,3,4,5と増えてった
9:37 AM
@かっくん 試したのってSwift 4.1 Developmentのスナップショットですか?
9:37 AM
僕が試したのは Trunk Development (master) なのでそこの違いかもしれません。
Avatar
かっくん 12/5/2017 9:38 AM
@omochimetaru そうです! ☝ の2番目の画像のスナップショットです!
Avatar
omochimetaru 12/5/2017 9:40 AM
あ、なるほど、 Swift 4.1 Snapshot になっていますね。こっちでは Swift Development Snapshot になっていました。
🤘 1
9:40 AM
ダウンロードできたら試してみます
9:44 AM
structのhashValueジェネレータ (edited)
9:46 AM
ここにコメントで全部書いてあったわ
Avatar
var result: Int result = _mixForSynthesizedHashValue(result, 1) 初期値無いように見えるけど
Avatar
omochimetaru 12/5/2017 9:48 AM
最後に謎のシャッフルがかかってる
Avatar
enumのほう
9:48 AM
これは初期値0の誤植かな
Avatar
omochimetaru 12/5/2017 9:49 AM
ほんとだ
Avatar
PRチャンスでは!!?!?!?!?
Avatar
omochimetaru 12/5/2017 9:50 AM
たしかに・・・
Avatar
これそもそも最初にresultと1を_mixForSynthesizedHashValueに入れる必要もないよね
9:51 AM
0&*31&+1になるんでしょ、1じゃん
9:51 AM
実際のenumの生成はここで、この行がcaseごとのループ
9:52 AM
そのforループより上にvar result の生成はある
Avatar
じゃけcase毎にresult作る、AssocValuesをループする前に0,1,2,3...で初期化される、ということでいいんじゃない
9:54 AM
そうすると result = _mixForSynthesizedHashValue(result, 1) // 🙅 result = 1 // 🙆 ってことだよね
Avatar
omochimetaru 12/5/2017 9:54 AM
だね
Avatar
おもち、じゃんけんだよ
Avatar
omochimetaru 12/5/2017 9:54 AM
で、 associated value があったら
9:54 AM
payloadVar (associvalues) についてのループで
9:54 AM
_mixForSynthesizedHashValueでの足し込みが生成される
9:55 AM
ジャンケンとは
✌ 1
9:59 AM
俺は別にプルリク出したいとは思ってないので出したければどうぞ
Avatar
swift-4.1-DEVELOPMENT-SNAPSHOT-2017-12-04-aはConditional Conformanceのビルド通るね。 struct Box<T> { let value: T } extension Box: Equatable where T: Equatable { static func == (lhs: Box, rhs: Box) -> Bool { return lhs.value == rhs.value } } Box(value: 1) == Box(value: 2) Playground execution failed: error: PlayNow-20171205.playground:7:15: error: ambiguous use of operator '==' Box(value: 1) == Box(value: 2) ^ PlayNow-20171205.playground:2:17: note: found this candidate static func == (lhs: Box, rhs: Box) -> Bool { ^ 使えそうには無いけど。
Avatar
左様で
Avatar
[omochi@omochi-iMac swhash]$ export TOOLCHAINS=org.swift.4120171204a [omochi@omochi-iMac swhash]$ swift --version Apple Swift version 4.1-dev (LLVM cdc9836644, Clang f0e38d2044, Swift 7a0598c7dd) Target: x86_64-apple-darwin16.7.0 [omochi@omochi-iMac swhash]$ swift b.swift
10:02 AM
こちらも今確認できました。
10:02 AM
[omochi@omochi-iMac swhash]$ export TOOLCHAINS=org.swift.3020171204a [omochi@omochi-iMac swhash]$ swift --version Apple Swift version 4.1-dev (LLVM c698959a5c, Clang dff0a814ae, Swift 9fef06e59c) Target: x86_64-apple-darwin16.7.0 [omochi@omochi-iMac swhash]$ swift b.swift b.swift:6:1: error: conditional conformance of 'Box<T>' to 'Equatable' depends on an experimental feature (SE-0143) extension Box: Equatable where T: Equatable { ^
10:02 AM
この2つの違い、 $ swift --version だとほとんどわからんですね。
Avatar
https://github.com/apple/swift/releases/tag/swift-4.1-DEVELOPMENT-SNAPSHOT-2017-12-04-a は最終ブランチ前なので、ちょっと古かったです。
swift - The Swift Programming Language
Avatar
どっちも4.1-devを名乗る
10:04 AM
-enable-experimental-conditional-conformances の実装が取り込まれてないってことですか? > @rintaro (edited)
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 declare...
Avatar
[omochi@omochi-iMac swhash]$ cat b.swift struct Box<T> { let value: T } extension Box: Equatable where T: Equatable { static func == (lhs: Box, rhs: Box) -> Bool { return lhs.value == rhs.value } } print(Box(value: 1) == Box(value: 1)) print(Box(value: 1) == Box(value: 2)) print(Box(value: Box(value: 1)) == Box(value: Box(value: 1))) print(Box(value: Box(value: 1)) == Box(value: Box(value: 2))) [omochi@omochi-iMac swhash]$ swift -enable-experimental-conditional-conformances b.swift true false true false
10:07 AM
masterのほうは動いた。
10:07 AM
[omochi@omochi-iMac swhash]$ swift b.swift b.swift:11:21: error: ambiguous use of operator '==' print(Box(value: 1) == Box(value: 1)) ^ b.swift:6:17: note: found this candidate static func == (lhs: Box, rhs: Box) -> Bool { ^ Swift.Equatable:149:24: note: found this candidate public static func == (lhs: Self, rhs: Self) -> Bool ^ b.swift:12:21: error: ambiguous use of operator '==' print(Box(value: 1) == Box(value: 2)) ^ b.swift:6:17: note: found this candidate static func == (lhs: Box, rhs: Box) -> Bool { ^ Swift.Equatable:149:24: note: found this candidate public static func == (lhs: Self, rhs: Self) -> Bool ^ b.swift:13:33: error: ambiguous use of operator '==' print(Box(value: Box(value: 1)) == Box(value: Box(value: 1))) ^ b.swift:6:17: note: found this candidate static func == (lhs: Box, rhs: Box) -> Bool { ^ Swift.Equatable:149:24: note: found this candidate public static func == (lhs: Self, rhs: Self) -> Bool ^ b.swift:14:33: error: ambiguous use of operator '==' print(Box(value: Box(value: 1)) == Box(value: Box(value: 2))) ^ b.swift:6:17: note: found this candidate static func == (lhs: Box, rhs: Box) -> Bool { ^ Swift.Equatable:149:24: note: found this candidate public static func == (lhs: Self, rhs: Self) -> Bool
10:07 AM
4.1のほうはたしかにダメですね。型定義は通るけど == の呼び出しが死んじゃった
Avatar
swift-DEVELOPMENT-SNAPSHOT-2017-12-03-a 以降ですよね。>-enable-experimental-conditional-conformances (edited)
Avatar
// var result: Int // switch self { // case A: // result = 0 // case B(let a0): // result = _mixForSynthesizedHashValue(result, 1) // result = _mixForSynthesizedHashValue(result, a0.hashValue) に関しては、実装は _mixForSynthesizedHashValue 一回なので、コメントだけの問題かな?
Avatar
はい、コメント上のコードが間違ってるって話と思ってます
10:11 AM
This pr is improvement of comment. Seems SomeEnumWithAssociatedValues implements require result initial value.
10:11 AM
早い
Avatar
はい
🎉 2
10:14 AM
somke testってなんですか
Avatar
https://github.com/apple/swift/blob/master/docs/ContinuousIntegration.md 基本的にはインクリメンタルビルドで、macOS で iOS とかのテストを行わないテストです。
swift - The Swift Programming Language
💡 1
Avatar
In computer programming and software testing, smoke testing (also confidence testing, sanity testing, build verification test (BVT) and build acceptance test) is preliminary testing to reveal simple failures severe enough to (for example) reject ...
Avatar
smokeが動詞だと思っていた……
Avatar
この記事英語むずい・・・
10:18 AM
smokeのニュアンスがいまいちよくわからん
10:19 AM
もともとのスモークテストの意味は「水道管に煙を流し込んで漏れがないかをチェックすること」です。それが転じて、マザーボードの新しいものを使って電気を通して煙が上がらないかチェックすることをスモークテストというようになり、さらに転じてソフトウェアの基礎的なテストをスモークテストというようになりました。
https://heartsn.com/management/web-consulting/it-glossary/su-line/smoke_test/
😀 1
👍 1
10:19 AM
だそうです
Avatar
ほー
10:20 AM
物理的な話だった
Avatar
特にテスト領域の指定にけむりモクモクのニュアンスがあるわけじゃなかったのね。
10:20 AM
そのまんま煙でテストしてた話だった。
Avatar
今もやってんのかな
Avatar
最初煙が出るくらい回しまくるっていうニュアンスで、ストレステスト的なのかと思ってた。 (edited)
Avatar
ガスの元栓を閉めて屋内配管に圧力をかけて、圧力が下がっていかないかチェックするテストがガス設備の法定点検になってますね。 (edited)
10:22 AM
圧力が下がっていくならどこか漏れているので、そこで場所を特定するために煙入れそう。
Avatar
あ〜なるほど
10:23 AM
穴が見つけられるのか・・・まさに・・・
Avatar
ガス管だといつでも煙を入れられそうだけど、水道管だと一度水を入れてしまった後に煙を入れるのは難しそうだから、最初に水を入れる前のテスト的な感じになるのかな。
Avatar
Avatar
うーん、keyがIntでもStringでもないDictionaryはエラーになってくれるのがうれしそうだけど🤔(Conditional Conformance以降は非Codable化)
Avatar
KeyedContainerString, Int以外をキーとして使えるかどうか、ってのは本来 Encoder, Decoder 次第だと思うんだけどな。
Avatar
まあそれは仕方ないとしても、KeyRawRepresentable なモノはKeyedContainerへ入れて欲しい。
Avatar
本来 Encoder, Decoder 次第
それだとコンパイル時にチェックして型エラーにできなくないですか?共通の枠組みがあるからこそ型として縛れるのかと。
12:29 AM
CodableDictionaryKey みたいな associatedtype があって、デフォルトで String とかだといいのかな・・・。
12:29 AM
String|Int であってほしいけど。
Avatar
CodableってJSONとその仲間(Yaml)を意識したものなのか
12:29 AM
JSONより柔軟なシリアライザの場合も見据えたものなのか
Avatar
KeyがRawRepresentableなモノはKeyedContainerへ入れて欲しい。
これは IntString はそうしてほしいですね。
Avatar
よくわかってないけど、それによりそう
12:30 AM
jsonは完全な方式だと思ってたけど辞書のキーがたしかに文字列しか取れないという縛りがあるんだなあ
Avatar
@omochimetaru 扱える範囲が狭いほど型としての安全性が高まって、その範囲で汎用性が高いほど実用的なんじゃないかな?という意味では JSON はとても良いバランスだと思う。 (edited)
Avatar
でもそれなら名前をJSONCodableにするべきだと思う
Avatar
いや、 JSON っていうのは文字列のフォーマットで
12:32 AM
今はデータ構造を
12:33 AM
Number String Boolean Array Dictionary Null で汎用的に表す話をしてるから
12:33 AM
JSON ではないと思う。
12:33 AM
Dictionary は実際には [String: Value]
Avatar
そのディクショナリーにそのしばりがあるのが
Avatar
より正確に書くと
Avatar
json由来の不自然なしばりにみえる
12:34 AM
辞書のキーはHashとEqがあればいいから、その枠組みでもArrayがキーになれてよい
Avatar
Number: Value String: Value Boolean: Value [Value]: Value [String: Value]: Value Null: Value
Avatar
はい、その表現能力をとるなら、それってJSONCodableって概念にしておいたほうがよいような気がする。
Avatar
うーん、たしかに [Value: Value] でもいいかも?ちょっとまだ確信が持てない。
Avatar
たとえばバイト列がもてないし、逆にブールやナンバーがない体型もありえるので
Avatar
別に JSON に限った話ではないと思うんよね。
12:39 AM
DB のレコードを Codable で表すこともできるんじゃない?
Avatar
Kishikawa Katsumi 12/6/2017 12:40 AM
EquatableだったらキーになれるというのはSwiftの中だけの話なのでシリアライゼーションの仕様としては難しいんじゃないかな。
12:41 AM
文字列の同値性もそこまで自明ではないけど。
Avatar
たとえばバイト列がもてないし、逆にブールやナンバーがない体型もありえるので
この部分は JSON よりも広げてもある程度は問題なさそう。たとえばバイト列を JSON 化するときには文字列化すればいいわけだし。
12:45 AM
EquatableだったらキーになれるというのはSwiftの中だけの話なのでシリアライゼーションの仕様としては難しいんじゃないかな。
たとえば、 JSON で表せる値なら比較可能だと思うんですよね。 JSON value をキーとして許容する拡張された JSON 仕様を考えることはできそうな・・・。
Avatar
Kishikawa Katsumi 12/6/2017 12:52 AM
まあCodableがJSONの扱いを便利にするように寄ってる感じなのはそうかな。
12:53 AM
難しいと書いたけど、なんでもキーにできるというのもアリだとは思います。ただその場合例外ケースを考えていくのがすごく大変になるんじゃないかな。
Avatar
タイプセーフにしようとすると、 CodableDictionaryKey を持ってて、 JSONEncoderfunc encode<T>(_ value: T) throws -> Data where T : Encodable, T.DictionaryKey == String|Int みたいなことができないとダメな気がしてます。
Avatar
norio_nomura 12/6/2017 3:16 AM
仕様としてYAMLはキーに辞書も配列も使えるけど、各言語での実装がそうなってるとは限らない。
3:17 AM
キーが文字列だけというのは、まあ妥当な妥協点だとは思います。
3:21 AM
Conditional Conformanceが来てもDictionary: Encodable whereKey : Encodableは付いて欲しく無い気はする。
3:24 AM
Array, Set, Dictionary, and Optional all provide unconditional conformances to Encodable & Decodable that dynamically check whether their type arguments are Encodable/Decodable. Now that we have co...
Avatar
おお、↓なんですね・・・ extension Dictionary : Encodable where Key : Encodable, Value : Encodable
Avatar
Codableはそうするしかなくて
6:08 AM
Dictionaryのエンコード成功/失敗はErrorで初めてわかる、としかならないのでは
Avatar
omochimetaru 12/6/2017 9:45 AM
これはコンパイルできる protocol EventSinkProtocol { associatedtype Event func send(event: Event) } extension EventSinkProtocol { func asEventSink() -> EventSink<Event> { return EventSink.init() } } class EventSink<Event> : EventSinkProtocol { func send(event: Event) {} }
9:45 AM
これがコンパイルできない protocol EventSinkConvertible { associatedtype Event func asEventSink() -> EventSink<Event> } protocol EventSinkProtocol : EventSinkConvertible { func send(event: Event) } extension EventSinkProtocol { func asEventSink() -> EventSink<Event> { return EventSink.init() } } class EventSink<Event> : EventSinkProtocol { func send(event: Event) {} }
9:46 AM
これはコンパイルできる protocol EventSinkConvertible { associatedtype _Event func asEventSink() -> EventSink<_Event> } protocol EventSinkProtocol : EventSinkConvertible { associatedtype Event = _Event func send(event: Event) } extension EventSinkProtocol { func asEventSink() -> EventSink<Event> { return EventSink.init() } } class EventSink<Event> : EventSinkProtocol { func send(event: Event) {} }
9:47 AM
これもコンパイルできる protocol EventSinkConvertible { associatedtype Event func asEventSink() -> EventSink<Event> } protocol EventSinkProtocol : EventSinkConvertible { func send(event: Event) } extension EventSinkProtocol { func asEventSink() -> EventSink<Event> { return EventSink.init() } } class EventSink<E> : EventSinkProtocol { typealias Event = E func send(event: E) {} }
Avatar
えっと
Avatar
omochimetaru 12/6/2017 9:47 AM
「3段構成+型パラとassocitype名が同じ」ときにうまくいかない
9:48 AM
RxSwiftでは3段構成だったが protocol の方は E で 型パラは Event にして回避してた。でも Swift の Array と Sequence はどっちも Element だから 名前は同じにしたいけど無理なんかな
Avatar
assoctypeとGenerics parameterは同名であってもマッチしないのは前からそうだね
Avatar
omochimetaru 12/6/2017 9:49 AM
ん、それだと例1 が通るのが変じゃない?
Avatar
1はフィールドでマッチングできる
9:49 AM
フィールドでマッチングした場合のみtypealiasの記述が省略可能
Avatar
omochimetaru 12/6/2017 9:49 AM
2の場合は間接的だからダメなのか
Avatar
protocol extensionにフィールドがある場合はprotocolをconformした側は情報が皆無なのでダメ
Avatar
omochimetaru 12/6/2017 9:50 AM
2の場合に、名前が同じだから typealias をしようとしても 左辺と右辺が同じになってしまってできない
Avatar
それなーー
9:50 AM
僕はもうGenericsParameterの名前付けを諦めた
Avatar
omochimetaru 12/6/2017 9:50 AM
protocolのほうをきれいな名前にした?
Avatar
そう
Avatar
omochimetaru 12/6/2017 9:51 AM
RxSwiftとは逆だね
Avatar
あっ
9:51 AM
しまったな、DelegateProxyはGenerics側がDとPなんだよね
9:52 AM
このスレってこの話題かな(読んでない
9:56 AM
とりあえず型パラを汚くすっか
Avatar
因みにProtocolにconformしてしまえば、中でもProtocolのassoctype名で使えるから
Avatar
omochimetaru 12/6/2017 9:57 AM
あ、たしかに
9:57 AM
最初のtypealiasぐらいか?悲しいの (edited)
Avatar
僕はGenericsを汚くする派です
9:57 AM
そね
Avatar
omochimetaru 12/6/2017 9:57 AM
なるほど!
Avatar
↑のメールはまた違う話題だったけど
11:59 AM
現状のassoc type推論を整理して新しいルールにして、わかりやすくする提案だった
Avatar
お、この前 EasyImagy の ImageImageSliceImageProtocol を導入しようとして同じ問題踏んだかも。なんで ArraySequence でできてるのに、って思った。
2:23 PM
でも最終的にできてるな。確か大分 ImageProtocol 側の API を削って。その前はコンパイルエラーになって、その後セグフォになって、仕方なく色々削って通ったんだった。なので別の問題か? https://github.com/koher/EasyImagy/blob/dev-0.4.0/Sources/EasyImagy/ImageProtocol.swift
EasyImagy - Makes it easy to process images in Swift
Avatar
エスパーするとassociatedtypeにconstraintつけるとちょこちょこセグフォ出ることあったんでそれですかね?
2:06 AM
Recursive Constraint以降は改善するかなと予想してます
Avatar
うーん、何が原因だったのか思い出せません😅
Avatar
https://qiita.com/tarunon/items/844958accc4391097d97 の件、とりあえず↓だけでも禁止してほしいです。 class A { func foo() -> Int? { return nil } } class B : A { override func foo() -> Int { return 42 } }

はじめに

SwiftのOptionalを取り巻くあれやこれやについて考えを整理しつつ書きます。 多くの人にとっては役に立たない雑多な話題かもしれません。差し当たりSwift EvolutionのDraftのDraftぐらいの話でし...
Avatar
これも問題なんですよね
Avatar
これの邪悪なのは、暗黙の型変換じゃなくて、 T is T? のサブタイピングが成り立ってしまってるとこです・・・。
Avatar
これとGenericsに関しては成り立っちゃってるんで
7:28 AM
完全に仕留めないと
Avatar
↓の邪悪だけどギリ暗黙の型変換と解釈できる・・・。 let f: () -> Int = { 42 } let g: () -> Int? = f
Avatar
functionの引数返り値がGenericsの範疇みたいな解釈だとアウト
Avatar
でも var a = 0 let f: () -> Int = { a += 1; return a } let g: () -> Int? = f
7:31 AM
として
7:32 AM
f() // 1 g() // 2 なのでアウト?
7:33 AM
↓と解釈すればインスタンスを共有してるわけではなく OK か。 let g: () -> Int? = { f() }
Avatar
実際には多分、let: g () -> Int? = { .some(f()) } なんですよね (edited)
7:34 AM
今考えてるのは、
7:34 AM
Optional wrap operatorみたいなのがあって、TとT?の共変性は全部廃止!っていうのが
7:34 AM
普通に一番筋が良いのではというの(過激派並みの発想)
7:34 AM
とりあえず?を使うとして、
Avatar
僕はオブジェクトは共有されてて、代入時にラップされてるだけなんじゃないかと思ってます。
Avatar
let intOptional: Int? = 1?
7:35 AM
こう
Avatar
気持ちはわかりますが、実現性は厳しいんじゃないかと思います・・・。
Avatar
デスヨネー(´・ω・`)
Avatar
あと、 foo?.bar のパースが・・・。
7:36 AM
foo?.bar はこれまで通りで、 (foo?).bar とかかな。
Avatar
そこは区別つくだろうとは思っています
Avatar
とりあえず、サブタイピングを始末するくらいなら現実味がある気がするんですよね。
7:37 AM
暗黙の型変換はさすがにもう厳しいんじゃないかと思います・・・。
Avatar
Array/Optionalをオーバーロードして普通のは別名っていうユースケースが
7:38 AM
暗黙の型変換を倒さないと安息は得られなくてここが厳しい
Avatar
「普通の」ってなんですか? map みたいなこと?
Avatar
map/flatMapがその代表
7:39 AM
Qiitaにも書きましたが、RxのObservable.just/Observable.fromもそれです (edited)
7:41 AM
モナドはこの関数、値はこの関数、っていう括りがOptionalの変換で破壊されてしまうので心中穏やかになれないんですよね
Avatar
第三のOptionalを提案するとか
8:12 AM
暗黙的変換の許されないOptionalで、関数の引数や返り値として使うことを意図しています
8:13 AM
ダメだ、nullのある言語にOptional追加しましたみたいなことになる未来が見える
Avatar
暗黙の型変換は諦めて、型システムをぶっ壊してしまってるサブタイピングだけは許容しないという方向で行くのが現実的じゃないですかね〜。
Avatar
ですね
8:17 AM
とりあえず外堀を埋めて
8:18 AM
民草が慣れてきたら次です
Avatar
これ変更してCoWに影響でてパフォーマンス変わるか?と懸念していて確かめてみたけどパフォーマンスには影響しなさそう。 import Foundation class Animal {} class Cat: Animal {} protocol Plant {} class Dandelion: Plant {} func address(of object: UnsafeRawPointer) -> String { let addr = Int(bitPattern: object) return String(format: "%p", addr) } let cats = [Cat()] let animals: [Animal] = cats address(of: cats) address(of: animals) // CoWが働いているのでcatsとアドレスは同じ let dandelions = [Dandelion()] let plants: [Plant] = dandelions address(of: dandelions) address(of: plants) // Plantは存在型なのでCoWは働かない? let ints = [1, 2, 3] let oints: [Int?] = ints address(of: ints) address(of: oints) // OptionalでラップするのでCoWは働かない (edited)
Avatar
norio_nomura 12/8/2017 4:19 AM
final re-branch後最初のスナップショットが出てた swift-4.1-DEVELOPMENT-SNAPSHOT-2017-12-07-a
Avatar
omochimetaru 12/8/2017 8:40 AM
internal protocol FactoryInitializable { init(factory: () -> Self) } extension FactoryInitializable { init(factory: () -> Self) { self = factory() } } public protocol DisposerProtocol { func dispose() } public class Disposer : DisposerProtocol, FactoryInitializable { internal init(void: Void) {} public convenience init<X: DisposerProtocol>(_ base: X) { self.init(factory: { Disposer.init(void: ()) }) } public func dispose() {} } public class EventEmitter<Event> { private class Unsubscriber : Disposer { public override func dispose() {} } }
8:40 AM
$ swift -O だとコンパイラが戻ってこないコード
8:41 AM
CPU使用率が99%に張り付く。
Avatar
FactoryInitializableをextensionに隔離したほうが良さそう
Avatar
omochimetaru 12/8/2017 8:41 AM
でも snapshot org.swift.3020171206a だと大丈夫。
Avatar
なんだっけ、extension含めアクセス修飾子がconfuseだからなんとかすっぺみたいなProposal
Avatar
omochimetaru 12/8/2017 8:42 AM
うーん、何の問題で何がどうして解決したのかわからん
Avatar
Kishikawa Katsumi 12/11/2017 12:14 AM
メタプログラミングの勉強にSwiftSyntaxを使ってPower Assertのライブラリを作ってみました。まだすごく不安定で、対応してない式の方が多いし、ちょっと書き方を変えると動かなくなったりして実用には難しいですが、よかったら見てください。また手伝ってくれる方がいたらとても嬉しいです。 https://github.com/kishikawakatsumi/SwiftPowerAssert
SwiftPowerAssert - Power Assert in Swift. Provides descriptive assertion messages.
👀 2
Avatar
やっぱり、コードインジェクションできるフックはあった方がいいのですねー。
Avatar
SwiftSyntaxってもう標準でimportできるようになったんですね
Avatar
4.1 toolchainが必要じゃないかな。
Avatar
あ、はい、「もう」というか、「4.1では」ですね
2:58 AM
標準っていうとたしかにxcode同梱リリースのことをさしてしまいますね。。
Avatar
masterブランチが標準の皆さん
Avatar
自前ビルドしないでswift.orgからtoolchainsで入れられるものはもう標準気分
Avatar
標準 #とは
Avatar
Kishikawa Katsumi 12/11/2017 5:32 AM
標準でビルドプロセスにフックできる仕組みが提供されると夢が広がりますね。
Avatar
それ欲しいですね〜
5:33 AM
swiftpmにプロポーザルとか過去にあったんかな
Avatar
野良アトリビュートが氾濫しちゃう世界になり得るという心配がある。
Avatar
Kishikawa Katsumi 12/11/2017 5:35 AM
間違いなくそうなるでしょうね。
Avatar
あ、言語側の拡張も含めた話ですか
5:35 AM
単純に swift build に前処理挟みたい
5:35 AM
xcodeでいう run script
Avatar
Kishikawa Katsumi 12/11/2017 5:36 AM
野良アトリビュートが氾濫する世界はそれはそれで悪くないですが、SwiftのFeaturesと同様にコミュニティで標準に組み込むものを決めるようにしたらいいんじゃないかと思っています。
Avatar
swift build に Run script phase欲しいわかる
5:38 AM
コンパイルの手前でコード生成したい
Avatar
コード生成をさせる方に進むのかコード生成が必要なくなる方に進むのか、どっちになるんだろ
5:39 AM
今は進んでないから仕方なくコード生成してるとして
5:40 AM
そもそも言語機能が揃ってないからどんなマクロが必要なのかもわからない、だった気がする
Avatar
とりあえずまだまだGenericManifestoにテーマは残ってるから
5:40 AM
そういうのはどんどん実装されて、それに該当するメタプロはどんどん不要になると思うけど
5:40 AM
実装されないラインがどっかで引かれて
5:40 AM
その時まだメタプロしたいシナリオが残ってれば
5:40 AM
それだけは自動生成になると思う
5:41 AM
combineLatestとかは
5:41 AM
可変長引数ジェネリクスがあれば自動生成は不要で
Avatar
そうだね
Avatar
C++は実際それがテンプレートでできるんで、自分はわりと不要になりそうだけど
5:42 AM
API定義からモデルの自動生成〜とかは
5:42 AM
Swift言語機能の枠組みを超えてる感がある
Avatar
わしはそう
5:42 AM
なのでコード生成のニーズはなくならないと思う。
Avatar
EquatableとかHashableの自動生成は言語機能側で最近対応されて
5:43 AM
Sourcelyのニーズが1つ減ったね。
Avatar
ProtobufとかSwaggerのモデルのコードが欲しいのは、API側で変更されるものであって、必ずしもswift buildに必要という感じでは無さそう
5:44 AM
SSSだと話は別か
Avatar
SSSの場合はAPI定義書がSwiftの型定義そのものになってほしいね。
5:46 AM
一個モデル書いてCodable準拠しとけばサーバクライアント両方実装終わりってできると思う
Avatar
Kishikawa Katsumi 12/11/2017 5:47 AM
ソースファイルを生成されるものは私はまあ必要悪だと思うので、CodableやHashableのようにSwiftの標準機能でサポートされるのはいいと思います。
5:48 AM
それとは別にPowerAssertのようにAssertメソッドのインストルメントしたいという場合や、指定したメソッドにロギングやトラッキング・パフォーマンス計測のコードを挿入したいとかあると思うんですよね。
Avatar
ロギングとパフォーマンス計測については
5:50 AM
TypeScript の Decorator みたいな言語機能で整理できるかも・・・?
Avatar
Kishikawa Katsumi 12/11/2017 5:51 AM
そうですね。TypeScriptのそれはよく知らないですが、名前からしてコンパイラプラグインのようなものですかね。
5:51 AM
function f() { console.log("f(): evaluated"); return function (target, propertyKey: string, descriptor: PropertyDescriptor) { console.log("f(): called"); } } function g() { console.log("g(): evaluated"); return function (target, propertyKey: string, descriptor: PropertyDescriptor) { console.log("g(): called"); } } class C { @f() @g() method() {} }
5:52 AM
クラスCのメソッドmethod に デコレータfとデコレータgを適用している例 まあ、JSの動的性に依存した実装ですけど。
5:52 AM
PowerAssertはかなり自由なフックが必要そうですねえ〜
5:53 AM
AngularJS2がこのデコレータを活用してて初めて見た時ひっくりかえった。
Avatar
Kishikawa Katsumi 12/11/2017 5:56 AM
と、書いてると、確かに仕組みが公開されたら野良アトリビュートが氾濫するというのは避けられないけど、本当に必要なケースはさっき書いたのとシリアライズくらいだから案外うまくいくかもしれない。
5:57 AM
静的にコード生成するしかなくて、そっちに比重がよりすぎるよりはいい気がします。
Avatar
decorator に似た話だと、 https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md ってのも有りましたね。
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
!!!こんな提案あったのか
Avatar
Kishikawa Katsumi 12/11/2017 5:59 AM
あ、Property Behavoour。ありましたね。
Avatar
KotlinのDelegated Propertyに似てますね これ欲しいんだよな・・・
Avatar
Kishikawa Katsumi 12/11/2017 6:00 AM
Realmでもこれをうまく使えないか議論した記憶があります。
Avatar
Python 知っている方は、 Python の ディスクリプタみたいなものと思ってください < property behavior
Avatar
↑の提案で Delayed Initialization も触れられてますね
6:03 AM
This can avoid the need for implicitly-unwrapped optionals in multi-phase initialization
6:03 AM
これあると IBOutlet の場合の IUO不要にできる
6:03 AM
Status: Deferred
6:03 AM
6:03 AM
先送り
Avatar
IBOutletのIUO不要はアツい
Avatar
tarunon自分で実現してなかったっけ、 lazy undefined みたいな技で (edited)
Avatar
それはObjC互換がないのでIBOutletで使えない (edited)
Avatar
あ、なるほど。
6:05 AM
Review入りしてDeferredになったくだりだけあとで読んでみよう。
Avatar
func undefined<T>() -> T { fatalError() } class Foo { lazy var foo: Int = undefined() }
6:06 AM
これね
Avatar
それほんとウケる
6:06 AM
天才
Avatar
これ使うとIBOutlet以外のIUO全部消える
Avatar
IUOは「nilを再代入できる」機能があるのでそれを使ってない、初期化遅れの場合の話しやね
Avatar
nilを再代入出来るのがイヤイヤのイヤだったのでこれを作った
Avatar
↑の undefined おもしろいですね。
Avatar
巧妙ですよねw
Avatar
Never が bottom になれば↓ができるのに。 func undefined() -> Never { fatalError() }
Avatar
なるほど
Avatar
なんなら return すらできる。
6:17 AM
func undefined() -> Never { return fatalError() }
6:18 AM
↑( Neverreturn )は今でもコンパイル通るけど、 Never が botton type じゃないから、任意の型に代入するとこができない。
Avatar
return強制したほうがきれいな気もするな。
Avatar
最後の式が return になる言語だとキレイなんだけどね。
6:19 AM
throw とかも考えると return 強制も変だし。
Avatar
なるほど
Avatar
Kotlin では throw Nothing を返すはず。 (edited)
Avatar
a ?: throw Exception とかできるんでそのはずですね
Avatar
うん
Avatar
perlの a or die を思い出す
Avatar
そこで botton type が利いてるのおもしろい。
Avatar
Scalaもまさにそんな感じですね
Avatar
多分 Scala がそうで、 Kotlin がそれを採用した流れですよね。
Avatar
??? can be used for marking methods that remain to be implemented.
メソッド名w
Avatar
あんま関係ないけど、 Kotlin が ?: 採用したのに三項演算子廃止したのよくわからない・・・。
Avatar
?: は2項だからセーフ?
Avatar
ところでいつになったら↓は Proposal が出されるんだろう? Never as a universal "bottom" subtype An uninhabited type can be seen as a subtype of any other type--if evaluating an expression never produces a value, it doesn't matter what the type of that expression is. If this were supported by the compiler, it would enable some potentially useful things, for instance using a nonreturning function directly as a parameter to a higher-order function that expects a result (array.filter(fatalError)) or allowing a subclass to override a method and covariantly return Never. This can be considered as a separate proposal. Moving from @noreturn to -> Never is not a regression here, since the compiler does not allow an arbitrary conversion from @noreturn (T...) -> U to (T...) -> V today. The most important use case, a nonreturning function in void context, will still work by the existing (T...) -> U to (T...) -> Void subtyping rule. https://github.com/apple/swift-evolution/blob/master/proposals/0102-noreturn-bottom-type.md#never-as-a-universal-bottom-subtype
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
6:25 AM
@omochimetaru ?:x ? y : z の省略形で x ?: z == x ? x : z 的に考えたら自然な演算子だけど( Nullable を Boolean のように使えればだけど)、 x ? y : z を廃止して ?: だけ採用したからよくわからない記法になってしまった感が。
6:25 AM
if (x) y else z でやれというのもわからんでもないけど。 (edited)
Avatar
それは c ? t : f からの c ?: f を知ってる前提なのでは。 ちなみにC言語にも ?: は実装されてますよ、標準だったか拡張だったかわすれたけど
Avatar
ほんとだ。 #include <stdio.h> int main(int argc, char *argv[]) { int a = 1; int b = 0; printf("%d\n", a ?: 42); printf("%d\n", b ?: 42); return 0; } 1 42
6:33 AM
やっぱり ?: だけ残ったのは気持ち悪い感が。
6:34 AM
Swift も flattenjoined になったけど flatMap だけ残っちゃったけど。
Avatar
そうですかねえ、僕はSwiftの ?? の方が、唐突な感じがします
6:34 AM
特に前例無いし。
Avatar
いや、?: が悪いんじゃなくて、三項演算子なくなさなくても良かったんじゃないの?と。
Avatar
ああ。
Avatar
Swiftの??、ネストしたOptionalでやるとオエーってなりそう、やってないからわからんけど
6:35 AM
また壊せそうな気がしてきた
Avatar
@tarunon さんが怒り狂いそうなコード。 let a: Int? = nil let b: Int? = a ?? nil // nil
Avatar
あーそれややこしいですよね・・・
6:38 AM
?? は 必ずしも右側でOptional剥がさなくてもいいんですよね
6:38 AM
thenみを感じる
Avatar
??は右側はOptional<T>/Tのオーバーロードなので
Avatar
(thenみ というのは mapとflatMapが同じシグネチャになる現象の事)
Avatar
let a: Int?? = nil let b: Int? = nil let c = a ?? b とかやると脳みそがスタックオーバーフローです
6:39 AM
この場合は.some(.none)になりそうだな
Avatar
https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%AB%E3%83%93%E3%82%B9%E6%BC%94%E7%AE%97%E5%AD%90
エルビス演算子をサポートした言語では以下のように記述すると、xにはf()結果がtrueと判定される場合にはその結果を、それ以外ではg()がセットされる。
println(false ?: true) // -> false
(edited)
Avatar
.none: Int? ではなく?
6:40 AM
1> let a: Int?? = nil a: Int?? = nil 2> let b: Int? = nil b: Int? = nil 3> let c = a ?? b c: Int? = nil
6:41 AM
よくこんな例ぱっと思いつきますね・・・
😯 1
Avatar
剥がすオーバーロードが優先なのね
Avatar
なるほど
Avatar
?? の右オペランドが Optional になるのは Haskell の <|> に相当しそう。 http://hackage.haskell.org/package/base-4.10.1.0/docs/Control-Applicative.html#v:-60--124--62-
Avatar
let a: Int?? = nil let b: Int? = nil let c = a ?? b // Int?.none let d: Int?? = a ?? b // Int??.some(.none) (edited)
6:43 AM
まあ一応整合性は取れてはいるか
Avatar
取れてるけど、やっぱ ?? のオーバーロードはダメな気がしてきました。
6:44 AM
??? にすればいいのに。
Avatar
オーバーロードとサブタイプが絡まりあって人間にもコンパイラにも理解できなくなる例がありそうだ
Avatar
↑まあそういう例において ??? と使い分けてたら読み解けるのかって疑問はあるけど
6:45 AM
マシではあるか・・・
Avatar
読み解けなくても間違えて書いたときにコンパイルエラーにできる?
Avatar
あー シンプルな例でもクサビになるのがいいですね。
Avatar
Never は、↓が盛り上がらなかったのが残念・・・ https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170508/036629.html
6:50 AM
何がうれしいって、 foo ?? fatalError("message") が書けるようになるのがうれしい。↓作ればいいという話もあるけど。 func fatalError<T>(_ message: String) -> T { fatalError(message) }
Avatar
omochimetaru - Today at 3:34 PM そうですかねえ、僕はSwiftの ?? の方が、唐突な感じがします 特に前例無いし。
C#にありますけどいつからあるんだろう?
Avatar
@koher これ多分、Swift.fatalError(message)にしないとシャドーイングで優先されて無限ループになりますよ
Avatar
fatalError よりも preconditionFailureassertionFailure かな。 ?? と一緒に使いたいのは。
Avatar
どっちにしても落ちますけどw
Avatar
どっちにしても
ww
Avatar
fatalErrorの実装としてスタックオーバーフローさせるのめちゃめちゃ行儀悪いなw
Avatar
@koher precondition とか assert だと最適化オプションによってはノーチェックになるので ?? と併用するのそもそも無理そうな気がするんですがその辺ってクリアできるものなんですか
6:55 AM
Neverとして扱えなそう
Avatar
assertionFailure は戻り値が Void ですが、 preconditionFailureNever なのでできますね。
6:55 AM
型の上では。
Avatar
お、 preconditionFailure はNeverなのか
Avatar
preconditionFailureはコンパイラで無視されるとそこから先の動きが保証されない
Avatar
@hiragram そこ面白くてpreconditionは消えないことになってて
Avatar
implicitly unwrapで未定義に突入したのと同じになる
Avatar
-Oundefinedで消える件については爆発する
6:56 AM
assertはOで消えるから消える事が考慮された型になってる。
6:56 AM
precondition: 建前上消えない assert: 建前上消える
Avatar
あー、そこがassertとpreconditionの違いになるのか。
Avatar
最近は fatalError の使い所って稀な気がしてて、↑のように assertionFailure 使いたいけど戻り値が Never じゃないから使えないケースで代わりに使うパターンが一番多い気がしてます。
Avatar
-O までは建前上正しい型システムで、 -Oundefined になると適当になる
Avatar
なんとなく「どの最適化レベルで消えるかが違う奴ら」というイメージしかしてなかった。
Avatar
型システム上の扱いで分けて考えるとスッキリするよね。
Avatar
お、そういえば preconditionassert についてはタイムリーなちょうどいい投稿がありますよw https://qiita.com/koher/items/ca7f388ab2a4e6747339
preconditionassert は似ているので、どういうケースでどちらを使うべきか意識してないと不適切な使い方をしてしまいます。本投稿では、 preconditionassert をどのように使い分け...
😎 2
🙂 1
Avatar
↑よみました。
Avatar
@omochimetaru > -Oundefinedで消える件については爆発する これはundefinedじゃなくてunchecked?
Avatar
あ、uncheckedか。
Avatar
ok
6:58 AM
@koher めちゃタイムリーでした。読みます。
Avatar
てっきりそれ読んだ上で話題にしたのかと思った。
Avatar
iOSDCで時間がなくて紹介できなかった宿題と (edited)
6:58 AM
Mobile Act OSAKA #2 と
Avatar
fatalError よりも preconditionFailure や assertionFailure かな。 ?? と一緒に使いたいのは。
これしかみてなかった @omochimetaru
Avatar
Qiita の Advent Calendar を
6:59 AM
全部一度に片付けましたw
Avatar
効率だ・・・
Avatar
assertとpreconditionの使い分け、自分はデバッグで落ちて欲しいけどリリースで落ちて欲しくない&どうにかカバーできるときはassert使ってるかな、そうじゃないときはprecondition
Avatar
そういうのは明示的に例外throw+catch+リカバリロジック+ログにしておくほうが良さそう
Avatar
最適化で assert が消えて素通りして落ちないのは意図しない挙動を引き起こすのでよくないと思います。
Avatar
privateメソッドの先頭で引数のバリデーションするのにassertつかってるくらいだなあ
Avatar
「カバーできる」事が明示的にコードで示せないのが気になります。
Avatar
throwはどっちかというとロジック的に問題ないけど予定外のことが起きたとき(JSONがデータが思ってたのと違う)とかに使ってるイメージ 🤔
Avatar
-Ouncheckedprecondition も同じですが、最適化でチェックが消えるのは、本来落としたいけど結果的に落ちなくなるだけなので、復活させたいなら OptionalError で対処するのがいいと思います。
Avatar
「カバーできる」事が明示的にコードで示せないのが気になります。
基本 guard との組み合わせで使ってるのでカバーは else 内で書いてますから一応ルート的に明示できてるはず 😇
Avatar
@lovee guardとassertを組み合わせると今度は return を書かないといけなくなってしまいません?
Avatar
@omochimetaru だから「どうにかカバーできる」んですよ?
Avatar
むむむ
7:31 AM
assertが書いてあるのはguardで分岐したelse節の中ってことですか?
Avatar
例えば let dictionary = [String: Int]() guard let value = dictionary["value"] as? Int else { assertFailure("needs value") return 0 } return value 的な
Avatar
カバーという言葉が意味するものが二人の間で違う
Avatar
いや、同じだね
Avatar
あれ、そうなの
Avatar
return dictionary["value"] ?? 0 ロジックとしてやりたいことは↑だけど右辺値の場合はデバッグモードでは死にたいのか。 (edited)
Avatar
@omochimetaru です
Avatar
デバッグで死にたくてリリースでは通したいシーンってぱっと思い浮かばないな
Avatar
ロジック上では dictionary には "value" あるはずなので
Avatar
とにかくクラッシュしてほしくない場合こうなっていきそうではある > @hiragram
7:35 AM
リカバーする動作、設計が先に想定されていて (edited)
7:36 AM
でもリカバーする場面は減らしたいから開発中は検知したい・・・
Avatar
func assertDefault<T>(_ message: String, _ defaultValue: T) -> T これで良さそう
Avatar
rx_fatalErrorみたいなのもこんな感じだったっけ
Avatar
rxのfatalErrorはそのまんまfatalError軒がする
Avatar
デバッグビルドだと落ちるよね確か
7:37 AM
リリースビルドだと警告出るだけじゃなかったっけ?
Avatar
error bindingのところは違う関数だったかな
Avatar
func bindingError(_ error: Swift.Error) { let error = "Binding error: \(error)" #if DEBUG rxFatalError(error) #else print(error) #endif } 呼び出し側か。チェックは
Avatar
@tarunon まあそのケースはそういうのでもいいけど
7:38 AM
一般論としてありえる気がする
7:38 AM
ようするになんかフローがあるんだけどDebug時は通らない立て札を立てるようなイメージ
Avatar
なるほど。確かにこれはあり得るかも?
Avatar
assert自体はフロー制御には介入して無くて
7:40 AM
むしろReleaseで消えるからNeverで無い事が
7:40 AM
必要になってる
Avatar
ふむ
Avatar
なんか発想の根本が逆向きというかなんというか。
7:41 AM
例えば好ましい前提ではないけど、他人が作った不安定なモジュールがあるとして、 ドキュメントとかもフワフワしているようなときに、
7:41 AM
ユーザサイドからみて仮定したい条件があるんだけど、もしかしたら成り立たないかもしれなくて、リカバリが可能な場合
7:41 AM
リカバー分岐ありで実装した上でassertionFailureを差し込んでおく
7:42 AM
というのはやりたいことがありそう。
Avatar
RxSwiftのここ、いやアサートでいいやんけ、っていうのはしばしば思ってるんだけどなんでそうなってるのか聞いたこと無いなそういえば
Avatar
うーん、でもよく考えたらリカバーコードが正しく動作することを検証できないから良くないような?
7:44 AM
リリースしたプロダクトに望む挙動は開発時にテストしたいのでは?
Avatar
開発時でもReleaseビルドにはできますよ
Avatar
まあそれはそうなんだけど。
Avatar
というか、「Debugビルドしか動作テストはしない」って正しいんですかね・・・?
7:45 AM
別の次元の問題だけど、Releaseビルドのほうがフレームレートが上がるから、ReleaseビルドじゃないとUXのチェックができないとか
7:45 AM
そういうのはよく踏む。
Avatar
正式リリース前のバージョンは一応リリースビルドで確認しますよね…?
Avatar
それはそうなんですが、どのみちエラーフローは実装しているわけで、ログさえ吐いておけばあえて落とす必要もない気も?
7:56 AM
うーん、複雑なフローだと落ちた方がわかりやすいとかあるかもですが・・・。
Avatar
プロダクトにもよりますが、ログだけしかないとログが長すぎて見逃しちゃった可能性も()
Avatar
わかる > ログ見逃し
Avatar
ログを人間が見るのが悪いのでは
Avatar
いくら派手にログメッセージ書いても気づいてくれないから殺したれってよく判断する
Avatar
ログを人間が見るのが悪いのでは
確かにこれはあるかもしれない 🤔
Avatar
確かにエラーメッセージを表示するとかではなく、正常フローと似た挙動をするときは気づかないかも? (edited)
Avatar
ややあって「ほら!そこにログが出てるでしょ!」って至るよりは、「なんか落ちたんだけど」って持ってきてもらったほうが話が早いのよな。
Avatar
確かにテストしてる人が実装した人とは限らないのでそっちの方が早いか。
Avatar
ここまで書いてログ発行のタイミングで自分のマシンに通知パケットが飛んでくれば最強な気がしてきた
Avatar
FabricにNon-fatal issueのシグナル投げておくみたいなことは結構やる
7:59 AM
クラッシュレポートと同じ情報としていろいろ通知来るし
Avatar
なるほど
Avatar
あとゲームに限った話かもしれないが、例えば画面エフェクトを実装してそれをスクリプト側で呼び出す、んでスクリプトが間違った時に落ちて欲しい、でも何かの間違いでプレイヤー側では思った通りのものにならなかった時にせめてゲームエンジン自体は動いて欲しい、画面エフェクトだけなくてもアプリとして一応動くから、と言ったものもassertの方が向いてる気がする(何かの間違いは一体なんなのかはさておき
Avatar
ちょっと話変わるけど↓変じゃないですか? Never じゃないからフロー殺せないし。 Use this function to stop the program, without impacting the performance of shipping code, when control flow is not expected to reach the call—for example, in the default case of a switch where you have knowledge that one of the other cases must be satisfied. https://developer.apple.com/documentation/swift/1539616-assertionfailure
Avatar
@lovee そういうのはスクリプトの実行をする関数がthrowsになってれば良いと思います
8:04 AM
てか最近のゲームよく落ちますよね
Avatar
@koher どのへんがおかしいですか?(ざっとよんだけどわからなかった)
Avatar
そんな低リスクの想定外の動作のために throws ばっかり使って do catch があっちこちに散らかってるのあまり好きじゃないかな
Avatar
@hiragram switchreturn してる場合とか、戻り値 Void だから defaultassertionFailure できなくないですか?
Avatar
ゲームエンジンとして絶対壊れちゃいけないBehavior Loopの根っことかで do - catch するイメージでした。
8:07 AM
んで、catchしたときは Behaviorのくっついてるオブジェクトの型情報とか読み込んでたスクリプトのログが出るような感じ。
Avatar
それはそれであらゆるメソッドが throws になってあらゆる呼び出しが try になって逆に try #とは って気持ちに
Avatar
なので、そういうケースでは本当は Logic failure からの復帰がほしくて
Avatar
それより上のレイヤーだともう多分どうしようもリカバリできないし、下のレイヤーだといろいろ呼び出しが相互に合わさるしスクリプトも差し込まれるからうまく切れなそう
Avatar
Java で言えば RuntimeExceptioncatch して処理したいんだけど
Avatar
あらゆるメソッドが throws になってあらゆる呼び出しが try になって
そこはそうですねえ・・・
Avatar
Swift ではそれが欠けてるんですよねぇ。
8:09 AM
actor の Proposal まだ読んでないけど、 actor が導入されたらその単位で殺したりできるようになるのかな?
Avatar
@koher それはそうですね。でもその英文はassertFailureをフローコントロールに用いるような感じの話じゃないんじゃないかと。「絶対そのcaseやdefaultに落ちないはず、みたいなコードパスに置いてね」くらいの意味と受け取りました (edited)
Avatar
「switch文のdefaultとかに使ってね」って読んだけど誤読なのか。
Avatar
直訳するとdefaultか
Avatar
for example, in the default case of a switch where you have knowledge that one of the other cases must be satisfied.
「たとえば、その他の case の一つが必ず満たされると知っているような場合の default case で」 じゃないですか?
(edited)
Avatar
「switch文のdefaultとかに使ってね」には preconditionFailure じゃないとリカバリコード書かないと通らないからどうなのよって話ですよね?
Avatar
です。
Avatar
はい。
Avatar
単にその英文がswitch以降も処理がいろいろある(=case句の中でreturnしない)ケースしか想定されずに書かれただけだと思うけどなあ
Avatar
あ、たしかに
8:14 AM
switch x { default: assertionFailure("bug") } hoge() fuga()
8:14 AM
これなら問題ないか。
Avatar
そうそう
8:14 AM
それを説明したかった英文なんだとおもっていたけど
8:14 AM
🌕 1
Avatar
なるほど。副作用のある処理とかならありえますね。
Avatar
ですね、これで何か予想外だけど致命的ではない問題が発生しても少なくともリリースビルドにはなんとかクラッシュせずに生き残れます、でもデバッグビルドではそれは検出できます
8:19 AM
致命的なものならpreconditionですが
Avatar
This is the second cut at implementing the DynamicMemberLookupProtocol proposal. Changes from PR13076 include: Incorporating @slavapestov's awesome code review feedback. Retroactive conformance t...
9:40 AM
もうPRきてた
9:40 AM
Pythonブリッジとかの下地のやつ。
Avatar
↑これめっちゃやる気満々だな。
Avatar
ですね
Avatar
これ通ったら、 Python で書いてる機械学習系のコード全部 Swift で書けるようになるのでは? (edited)
Avatar
構文がSwiftなだけのPythonになって型もないし別に嬉しく無さそうなのが・・・
Avatar
いや、データの前処理とか全部 Swift に持ってきて、そのまま TensorFlow とか scikit-learn とかにつっこめないかな?
Avatar
あっ、でも リスト内包表記とかラムダとかpythonの不満点は全部解消するか
9:57 AM
そういうのはできそうですね。
Avatar
Chris Lattner が今の部署にいる限り、 TensorFlow が動くのは第一目標だろうから、少なくともそこは使えるようになりそう。
9:59 AM
機械学習自体のコードよりも、付随コードが多くて辛いから、それが全部 Swift で書けるようになったらとてもうれしい。
Avatar
なるほど・・・
Avatar
Python 以外にも、↓の JSON の例おもしろいよね。 SwiftyJSON を単純化したようなのが( ["foo"] じゃなくて .foo で)書けるようになる。 https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#example-usage
Avatar
we propose starting the transition on the afternoon (US Pacific time) of Thursday, Dec. 14, and completing the transition by Dec 18 (Monday).
Avatar
おおおお
1:57 AM
↓こんな感じになるのか(リンク先はプロトタイプ)。 http://swift.trydiscourse.com/
Swift Forums
1:59 AM
↓たまたまプロトタイプの Evolution の上の方に。 Markdown で書いてたからシンタックスハイライトされてる。 http://swift.trydiscourse.com/t/question-why-does-beginasync-rethrow-errors/6986
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...
Avatar
おーいいっすね
2:37 AM
githubでログインしようとしたら404だったwまだなのかな
Avatar
まだですね。
Avatar
テストのやつはログインできないってかいてあった
Avatar
Also note, we’re currently not supporting logins on the prototype site as we’re in the process of changing configurations.
Avatar
enum JSONNullable<T> : Codable { case value(T) case null func encode(to encoder: Encoder) throws { var sc = encoder.singleValueContainer() switch self { case .value(let anyValue): if let encodableValue = anyValue as? Encodable { // sc.encode(encodableValue) // だめ } else { // throw error } case .null: try sc.encodeNil() } } }
6:12 AM
JSONに noneのときに キーが無くなるのではなくて null を吐く Optionalを作ろうとしてるんですが
6:13 AM
↑ // だめ のところってどうやって書いたらいいんでしょう?
6:13 AM
I'm using Swift 4's JSONEncoder. I have a Codable struct with an optional property, and I'd like this property to show up as null value in the produced JSON data when the value is nil. However,
6:13 AM
case .some(let wrapped): try (wrapped as! Encodable).__encode(to: &container) SOでヤバそうなコードは見つけたんですけど。
6:14 AM
enum JSONNullable<T> : Codable { case value(T) case null func encode(to encoder: Encoder) throws { switch self { case .value(let anyValue): if let encodableValue = anyValue as? Encodable { // sc.encode(encodableValue) // だめ try encodableValue.encode(to: encoder) // } else { // throw error } case .null: var sc = encoder.singleValueContainer() try sc.encodeNil() } } }
6:14 AM
↑これで良いのか・・?
Avatar
↓はダメ? enum JSONNullable<T : Codable> : Codable { case value(T) case null ... }
Avatar
あ〜 まあ今はそれでもいいか・・・
6:19 AM
できれば、 T : Encodable なら : Encodable、 T: Decodable なら :Decodable が、うれしいですけど。
Avatar
CondConfが無いときのStdlibのOptionalの実装を真似したらできそう
6:24 AM
バグがあったりして @norio_nomura が治してたりしてたからここのログにあるんじゃないかな
Avatar
AnyEncodable だったりして
Avatar
stdlib内部だと内部だけの裏技とかもあったから・・・
Avatar
@norio_nomura さんがやってたのは YAML のサードパーティライブラリだったような? < 内部だけの裏技
6:26 AM
本体も直してたか
Avatar
いえ、stdlibも直してましたw
Avatar
本体にパッチ送ってましたね
Avatar
あ、あと、stdlibの場合は
6:28 AM
キーが無くなるんですよ
6:29 AM
JSONの。 今やりたいのは キーはなくさずに、 null を書きたいから
6:29 AM
まあでも他にヒント無いし見てきます
Avatar
今見た感じおもちのやりたいことで引っかかってるのはValueある方で引っかかってるように見えたから
6:29 AM
Optional見たら解けるでしょって思った
6:31 AM
6:37 AM
Optionalの場合は、自動生成だと、
6:37 AM
encodeIfPresentを呼び出しているようだった。
6:39 AM
OptionalもArrayも直接Decode/Encodeするわけじゃないから
6:39 AM
ギリギリ問題にならないのか
6:40 AM
もうちょっとでConditional Conformanceが来るのに・・・
Avatar
struct E : Error {} enum JSONNullable<T> : Codable { case value(T) case null init(from decoder: Decoder) throws { var sc = try decoder.singleValueContainer() print(71) if sc.decodeNil() { self = .null return } print(72) if let decodableType: Decodable.Type = T.self as? Decodable.Type { print(73) self = .value(try decodableType.init(from: decoder) as! T) } else { print(74) throw E() } } func encode(to encoder: Encoder) throws { switch self { case .value(let anyValue): if let encodableValue = anyValue as? Encodable { try encodableValue.encode(to: encoder) } else { throw E() } case .null: var sc = encoder.singleValueContainer() try sc.encodeNil() } } }
6:49 AM
@tarunon T = String でも print 74 にいっちゃうんだけどなんか前こんな分岐やってたよね
Avatar
あーこれは
6:49 AM
これはこれは。。。。
6:49 AM
ダメですね
Avatar
はい
Avatar
Swift4以降ダメになった気がする
Avatar
そんな話だった
6:50 AM
その時なんか知見あった?回避の。 (edited)
Avatar
回避は出来なかった気がする
Avatar
ふむ
Avatar
これ諦めてEncodable, Decodable, Codableで3種類型作ったほうがいいんじゃない?CondConfが来るまでのつなぎでしょ
Avatar
encodeは期待した挙動になったけど init (From decoder) がダメそうだな
6:52 AM
うんまあつなぎっちゃつなぎなんだけど
6:52 AM
動的にやる場合はどうなるのか/できないのか
6:52 AM
がよくわかってないのは気持ち悪くて。
Avatar
Encodableもうまく動いているように見えて、JSONのエンコードルールに従わないみたいな残念なバグが発生しそう?
Avatar
目前の課題としては T : Codable で一応大丈夫
6:53 AM
Encodableのほうはとりあえずはうごいたよ
Avatar
URLいれてJSONでやっても動くのかな
Avatar
URLは入れない方針で・・・
Avatar
それは動いてるとは言わない
😂 1
6:55 AM
これ近いことやったのいつだったかな
6:55 AM
DelegateProxyあたりかな?
6:57 AM
6:57 AM
これあれだ
6:57 AM
ウソのisの結果が帰ってくるから回避不能回避不能回避不能!!ってなったやつ
6:57 AM
諦めましょう
6:57 AM
今は無理です
Avatar
Avatar
DelegateProxyにあったウソのコードも消しました
Avatar
だめそうかあ。<T: Codable> にします、ありがとう。
Avatar
Playgroundで <# aaa #> って入力すると半クラッシュする (edited)
Avatar
半クラッシュ #とは
Avatar
上手く言えないのでやってみて
Avatar
半チャーハンみたいな?
Avatar
なんか明らかに処理系がクラッシュしてるんだけどXcodeレイヤーはセーフ
Avatar
ピンピンしてる
7:15 AM
Toolchainかな?
Avatar
Xcode9.2
7:15 AM
純正
Avatar
error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=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.
7:15 AM
ちゃんとこれが出る
Avatar
ああ、それそれ。
Avatar
てっきりSourceKit瀕死の方かと思った
Avatar
もはやこの程度は何も問題ないみたいな
Avatar
ちゃんとメッセージ出てるからセーフ
Avatar
Playground execution aborted Group file:///Users/omochi/work/playground/iOSGround.playground: error: Playground execution aborted: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=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.
7:17 AM
うん・・・ でも何も悪い事してなくない?
7:17 AM
正常な異常動作とでも言えばいいのか
7:17 AM
レポートしなくてもまあいっか、みたいな・・・
Avatar
thread return -x 見すぎて脳みそが勝手によしなに解釈するようになってしまった
Avatar
Fatal error: attempt to evaluate editor placeholder: file MyPlayground.playground, line 2 出てますよね?
Avatar
ss
Avatar
Int("")! とかもそうですけど、コンソールに加えて余計なエラー出ますね。
Avatar
そっちはまあ、プログラム実行時点でクラッシュするからわかるんですけど
7:37 AM
<# aaa #> の入力だけだったら、 普通にコンパイラで型エラーが見つかった時と同じような程度なのが正しい気がしてて
7:37 AM
(実際コマンドラインからやるときはそうなる)
7:38 AM
EXC_BAD_INSTRUCTIONが飛び出したメッセージが出てるのはApple的に期待されてない挙動なようなきもするし
7:38 AM
Xcode側は無事だから期待通り何かがハンドリングされた挙動なようなきもするし
7:38 AM
なんともいえない・・・
Avatar
https://github.com/apple/swift/blob/4c2d55d0134bd4fdb4e68eaf59bc9db0ceb1e220/lib/Parse/Lexer.cpp#L1882-L1888 意図的にエラーにしていないのは確かなんですが、その理由は僕は知らないのです。
swift - The Swift Programming Language
Avatar
お、Lexer.cppだ。
7:41 AM
これ昨日読んでいてこのいたずらを思いついた。
7:42 AM
ここだけ見る限り普通にDiagnoticsが流れるだけになりそうですよねえ。
7:42 AM
実際CUIならそうなるし、なんかXcodePlayground固有の何かが生じてそう
Avatar
diag::lex_editor_placeholderERROR として定義されていて、 diag::lex_editor_placeholder_in_playgroundWARNING なので、
7:44 AM
Playgroundの場合 Warning 出して identifier としてトークン化されて素通りっていう流れですね。
Avatar
Fatal error: attempt to evaluate editor placeholder: file iOSGround.playground, line 1 WARNING(lex_editor_placeholder_in_playground,none, "editor placeholder in source file", ()) https://github.com/apple/swift/blob/12e7caf5d71d441b95faeeae649d5afbbd57ab60/lib/Sema/CSApply.cpp#L3744
swift - The Swift Programming Language
7:49 AM
diag::lex_editor_placeholderが出そうとするメッセージは editor placeholder in source file"だけど
7:49 AM
今でてくるのは↑のCSApplyの中に書かれた
7:50 AM
な、なんだこれ、// Synthesize a call to _undefined() of appropriate type.
7:50 AM
クラッシュするコードにコンパイルされているのか
7:50 AM
あっ、そういうこと?
7:50 AM
ERRORが出ればそこで止まるけど
7:50 AM
WARNINGの場合はコンパイルまで進むようになっていて
7:50 AM
この部分がコンパイルされると死ぬコードになって
7:50 AM
Playground上で実行されて死ぬ
👌 1
7:51 AM
だから Int("")! と同じような見た目になるのか。
Avatar
おお、Fatal error: って見出しはここで書き足されてますね。
Avatar
enum Animal : Int { case cat = 2 case dog = 3 } func f(_ animal: Animal) {} // ok f(Animal.init(rawValue: 3)!) // error: iOSGround.playground:7:21: error: type of expression is ambiguous without more context f(.init(rawValue: 3)!)
8:22 AM
これ最近困ってるんですよね。そういうもんだっけ。
Avatar
この .init 可読性悪くない?w
Avatar
まあそれはおいといて・・・
Avatar
AppCode人間いるかな
8:25 AM
わかりにくい.initの左側に型が補完されて見えるかな?と思ってるけど
Avatar
enum Material { case fire case water init(_ x: Int) { self = .fire } } func g(_ material: Material) {} g(.init(3))
8:25 AM
↑こっちは、いけるから
8:25 AM
やっぱり rawValue enum 特有のバグではなかろうか??
Avatar
いや
8:26 AM
Optional initから推論出来てない気がする
Avatar
あ〜
8:26 AM
enum Material { case fire case water init?(_ x: Int) { self = .fire } } func g(_ material: Material) {} // error: iOSGround.playground:19:11: error: type of expression is ambiguous without more context g(.init(3)!)
8:26 AM
ほんとだ。
Avatar
あー、なるほど
Avatar
じゃあいいのか。
Avatar
たまたま Optional のケースを raw value で踏んだだけなのか〜
Avatar
enum Material { case fire case water init?(_ x: Int) { self = .fire } init(_ y: String) throws { self = .water } } func g(_ material: Material) {} try g(.init(""))
8:30 AM
throwsのほうが推論通しやすいわけか
Avatar
JSONNullableは解決したのかな?
Avatar
enum JSONNullable<T: Codable> : Codable { case value(T) case null 諦めてこれで対処しました
👍 1
Avatar
Kishikawa Katsumi 12/12/2017 2:05 PM
@koher https://qiita.com/koher/items/ca7f388ab2a4e6747339 <= この使い分けについて、preconditionの失敗はメソッドやAPIの使用者側の問題(責任)で、assertは提供者(作る側)の問題(責任)という理解で合ってますか?
preconditionassert は似ているので、どういうケースでどちらを使うべきか意識してないと不適切な使い方をしてしまいます。本投稿では、 preconditionassert をどのように使い分け...
Avatar
はい、そうです🙂
Avatar
Kishikawa Katsumi 12/12/2017 2:24 PM
ありがとうございます。とても腑に落ちました。例などがとてもわかりやすかったです。
😁 1
Avatar
お役に立ててよかったです😀
Avatar
preconditionの失敗はメソッドやAPIの使用者側の問題(責任)で、assertは提供者(作る側)の問題(責任)
なるほどこの切り分け方いいですね
Avatar
メタタイプの配列って[Any]としかできないのかな? let dateTypes = [Date.self, NSDate.self] // Heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional
Avatar
↓こうなりました。 1> class Animal {} 2. class Cat : Animal {} 3. class Dog : Animal {} 4. 5. let a = [Cat.self, Dog.self] a: [Animal.Type] = 2 values { [0] = Cat [1] = Dog } (edited)
Avatar
共通するのはCodableである、だけなのですよね。 import Foundation let dateTypes = [Date.self, NSDate.self] as? [Codable.Type] dateTypes?.count // nil
Avatar
protocol はダメみたいですね。 1> protocol Animal {} 2. class Cat : Animal {} 3. class Dog : Animal {} 4. 5. let a = [Cat.self, Dog.self] error: repl.swift:5:9: error: heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional let a = [Cat.self, Dog.self] ^~~~~~~~~~~~~~~~~~~~ as [Any]
12:27 AM
existential だから、普通のサブタイピングとはちょっと違うとは思うんですよね。
Avatar
メタタイプを表す型が欲しかったのだけど、無さげ。
Avatar
なるほど、そういう意味ですか。
12:29 AM
お、↓はできました。 1> protocol Animal {} 2. class Cat : Animal {} 3. class Dog : Animal {} 4. 5. let a: [Any.Type] = [Cat.self, Dog.self] a: [Any.Type] = 2 values { [0] = Cat [1] = Dog }
Avatar
お、
Avatar
Foo.Type.Type is Any.Type.Type はもちろん、 is Any.Type も成り立つみたいなので、メタタイプ一般を Any.Type で表せそうです。 1> protocol Animal {} 2. class Cat : Animal {} 3. class Dog : Animal {} 4. 5. let a: [Any.Type.Type] = [Cat.Type.self, Dog.Type.self] 6. let b: [Any.Type] = [Cat.Type.self, Dog.Type.self] a: [Any.Type.Type] = 2 values { [0] = Cat.Type [1] = Dog.Type } b: [Any.Type] = 2 values { [0] = Cat.Type [1] = Dog.Type }
12:32 AM
ってか、もはや Animal いらないですね。
12:32 AM
1> let a: [Any.Type.Type] = [Int.Type.self, String.Type.self] 2. let b: [Any.Type] = [Int.Type.self, String.Type.self] a: [Any.Type.Type] = 2 values { [0] = Int.Type [1] = String.Type } b: [Any.Type] = 2 values { [0] = Int.Type [1] = String.Type
Avatar
ありがとうございます! 🙏
🙂 1
Avatar
Any は型じゃないみたいなのあった気がするんですが、 Any.Type があるということは型になったんでしたっけ?🤔
12:36 AM
↓もできるし別にいいのかな??実行できてるけど謎のエラーが出てるけど。 1> let a: (Int, String).Type = (Int, String).self a: (Int, String).Type = (Int, String) error: could not fetch result -- error: Couldn't apply expression side effects : Couldn't dematerialize a: corresponding symbol wasn't found
12:36 AM
nominal type じゃないってだけだったかな??
Avatar
ノミナルじゃないだけで型ではあると思う
Avatar
: Any って書けるからそりゃそうか。 nominal かどうかという話と混同してたみたい。
Avatar
メタクラスの根っことしてのAny.Typeは結構使います
Avatar
Extend the mandatory unreachable diagnostic pass to cover naive infinite recursion. The algorithm used is roughly the one from Clang with Swift-specific modifications and some minor simplification...
2:22 AM
時々話題に出てくる循環呼び出しによるスタックオーバーフローをコンパイラで検出する機能のプルリクが立ったよ
2:23 AM
+func a() { // expected-warning {{all paths through this function will call itself}} + a() +} + +func b(_ x : Int) { // expected-warning {{all paths through this function will call itself}} + if x != 0 { + b(x) + } else { + b(x+1) + } +}
2:24 AM
+// Doesn't warn on mutually recursive functions + +func e() { f() } +func f() { e() } とりあえず相互再帰はだめみたい
Avatar
相互再起はできないだろうなぁw
Avatar
これ系は一般系が無理なだけで
2:24 AM
特定のパターンの検出器を作る事はできるから
2:25 AM
2つまでとか限定してならできるんじゃないか
2:26 AM
eを検査するときに出てくる呼び出しがなんだったか1つまで覚えておいて(この場合fを記憶する そのfの中で必ずeに突入するか検査するってかんじで。
Avatar
これがあると、同名の関数をオーバーロードしてエイリアスを作ったと思っていたら優先順位が自身の方が高くて死亡、というケースが稀にあってそれが助かる (edited)
Avatar
どうだろうオーバーロードがあっても動くかはまだわからんw
2:26 AM
シンプルなケースだけという実装の可能性も
2:26 AM
(コミットされてるテストケースではオーバーロードされてるパターンは無い)
Avatar
function見てるだけだからオーバーロードはあんまり関係ないと思った
2:28 AM
オーバーロードは人間が認知するときだけの問題でコンピューターから見たら他の関数の差と大して違わないと思う
Avatar
オーバーロードの呼び出しとかが解決した後の後段での検査なら関係ないか。
2:29 AM
Resolves SR-626, SR-677, SR-2559, and SR-4406 Has implications for SR-3016, SR-5224.
2:29 AM
関連issue多い
Avatar
@hiragram import UIKit protocol ProtocolA { init?(coder: NSCoder) static var name: String { get } } class CustomCell: UITableViewCell, ProtocolA { required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } static var name: String { return "CustomCell" } } class ProtocolACellFactory { init<X: UITableViewCell & ProtocolA>(_ type: X.Type) { _build = { X.init() } _name = { type.name } } func build() -> UITableViewCell & ProtocolA { return _build() } var _build: () -> UITableViewCell & ProtocolA var _name: () -> String } func hoge(cellFactory: ProtocolACellFactory) {} let cells = [ProtocolACellFactory.init(CustomCell.self), ProtocolACellFactory.init(CustomCell.self), ProtocolACellFactory.init(CustomCell.self)] cells.forEach { hoge(cellFactory: $0) }
Avatar
ゴリ押したw
2:54 AM
でもそのコード、ユーザー側に露出するのでいちいちfactoryでwrapするのめんどい話があって
Avatar
ProtocolACellFactory自体はメタクラスじゃないけど目的は果たせそう
Avatar
適当なオペレーター作りたいね
Avatar
registerCellがしたいなら UITAbleViewCellオブジェクトを返す機能もFactoryにたせばOK
Avatar
TableViewCellのprotocol extensionに.typeFactoryなstatic var生やせばいいか
3:01 AM
あー
3:01 AM
@hiragram 別のアプローチ思いついたんで後で確認して貼ります
3:03 AM
までも、おもちのやり方に近いかな
Avatar
おけ、大体まとまった。 @hiragram ひらりのやりたいことはTableViewに生えているCell&Protocolを満たす関数を連続で呼び出したい、ということ。 extension UITableView { func register<Cell>(_ type: Cell.Type) where Cell: UITableViewCell, Cell: SomeProtocol { ... } } このregister関数は事実上UITableviewとCell.Typeの二引数関数なので、Cellから見れば自身のパラメータを埋めてあげればUITableViewだけの一引数関数を準備できる。 extension SomeProtocol where Self: UITableViewCell { static func register(to tableView: UITableView) { tableView.register(self) } } こうすると、Cell.registerが全て(UITableView) -> ()の型になるので、それを配列で処理する関数をUITableView側に準備してあげれば、 extension UITableView { func registerAll(_ registers: [(UITableView) -> ()]) { registers.forEach { $0(self) } } } 使う側もスッと書けるようになりました。 tableView.registerAll([MyCell1.register, MyCell2.register, MyCell3.register]) (UITableView) -> ()の型でabuseが気になるなら、これを一枚ラップして全部隠せば大丈夫ですね。 (edited)
Avatar
今気づいた
Avatar
API のネーミングの相談です。↓は EasyImagy の Image 等を直接ファイルに保存するメソッドなんですが、できるだけ標準ライブラリや Foundation を踏襲したいと考えています。 func write(to url: URL, atomically: Bool, formatting format: Image.Format) throws 参考にしたのは NSString の↓です。 func write(to url: URL, atomically useAuxiliaryFile: Bool, encoding enc: UInt) throws ただ、 formatting: .png に違和感があって、 formattedAs: .png とか as: .png とかな気もするんですがいかがでしょう?でも、なんで encodedAs: .utf8as: .utf8 じゃないんだという話になりますが。 (edited)
Avatar
encoding は名詞とすると、 format: .png でいいんじゃないかと思います。
Avatar
うーん、名詞なんですかね? write to the url atomically encoding UTF-8 は一応 encoding 以下を副詞句としてみたら英語として成り立つような。 (edited)
12:59 AM
似たようなのでは NSBitmapImageRep.FileType https://developer.apple.com/documentation/appkit/nsbitmapimagerep.filetype があるんですが、位置的に using: でしか使われてないんですよねぇ。 https://developer.apple.com/documentation/appkit/nsbitmapimagerep
1:00 AM
EasyImagy も Data に変換する方は↓にしてます。 func data(using format: Image.Format) -> Data?
1:01 AM
これは NSString 等の func data(using encoding: UInt) -> Data? と同じです。
1:01 AM
あーでもここも encoding ですね。
1:02 AM
じゃあさっきのも名詞なのかな・・・。
Avatar
formatting: .png as: .png formattedAs: .png format: .png だと個人的には format: が一番わかりやすいです。正しさは置いておいて。 (edited)
Avatar
僕もencodingが名詞だからformatが良いと思いました Encodingって言葉は型名でも使われてるのもあってそう見える
Avatar
了解です。 format: の方向で、もう少し色んな API を調べてみてから変更したいと思います。
1:21 AM
--- あと、もう一つ困ってるのが画像を 90 度単位で回転させるメソッドで、任意角度で回転させるメソッドは func rotated(by angle: Double) -> Image<Pixel>CGAffineTransform の↓に倣ってるんですが、 func rotated(by angle: CGFloat) -> CGAffineTransform 90 度単位で n 回回転させたいって times を後ろに付けることができないし、 API Design Guidelines にもそんな例はないしどうしたらいいものかと。 (edited)
1:23 AM
今は↓で誤魔化してるんですが、気に入らないので修正したいなと考えてます。 func rotated(_ times: Int) -> Image<Pixel>
1:27 AM
rotatedOrthogonally(_) に変えるとか、 ratated(n, .times) で呼び出せるようにするとか、 rotated(byDegrees angle: Int) にして 90 の倍数のときだけ特殊処理をするとかあるかなとも思うんですが(ラジアンではなく度で受ける byDegreesNSView のメソッドで見られます)、最後のパターンは 90 度以外のときに余白を埋める必要があり、デフォルトの Pixel の値がわからない任意の型では使えなくなってしまいます( 90 度単位では余白が存在しないので問題ない)。引数が Int 版は 90 度単位でない場合は実行時エラーにすることもできますが、 times ならエラーがないのに微妙だなと。 (edited)
Avatar
orientationではだめですか?
Avatar
@_ha1f それも考えたんですが、 -1 とか 100 とか指定したいときに不便かなと。
1:30 AM
rotated(-1) で反時計回りに 90 度回せると便利だろうなと。
1:31 AM
えっと、意図としては n の部分が計算によって得られるケースで enum に変換するのがめんどそうだなということです。
1:31 AM
% は負の数は結果が負になってしまいますし。
Avatar
それだと似たようなのはnumpyのrot90とかですかね
Avatar
@t.ae できるだけ Swifty なネーミングにしたいです。
1:32 AM
API Design Guidelines に沿っていて、かつできれば既存の API を踏襲できると一番いいです。
1:34 AM
うーん、 rotated(by angle: Int) にして、 90 度単位で特殊処理、それ以外はデフォルト値の存在する Pixel 以外では実行時エラーとかがいいのかな・・・。
Avatar
enumが良いと思います
Avatar
なるほどです。個人的にはあくまでインターフェースはライブラリ側の仕様にあわせて、enumへの変換は呼び出し側の責務な気がします (edited)
Avatar
enum RotateAngle90 : Int { case _0 = 0 case _90 = 90 case _180 = 180 case _270 = 270 } (edited)
Avatar
rotated(_ Orientation:)rotated(.forDegree(deg)) で生成出来るようにしておけば。 (edited)
Avatar
@_ha1f 呼び出し側の責務なのはその通りなんですが、使い勝手が悪くないと良いなと。 (edited)
1:38 AM
@omochimetaru _ が微妙・・・
1:39 AM
@rintaro .forDegrees が 90 度単位以外は実行時エラーと同じことになりませんか?
Avatar
ま〜シンボルってわかりやすくて良いし。
Avatar
enum Angle { case r0 case r90 case r180 case r270 case custom(Double, default: Pixel) } とかかなぁ。 (edited)
1:41 AM
deg90 とかの方がいいか。単位が明確で。 (edited)
1:42 AM
enum Angle { case deg0 case deg90 case deg180 case deg270 case deg(Double, default: Pixel) init(rotationTimes: Int) { if rotationTimes >= 0 { switch rotationTimes % 4 { ... } } else { ... } } } (edited)
Avatar
swift的に省略語はあまり良くないのでは
1:42 AM
deg より degree が良さそう。 (edited)
Avatar
省略語というか単位? [deg] 的な
1:45 AM
うーん、 rotated(byDegrees angle: Int) の方が圧倒的にシンプルな感じが。 (edited)
1:46 AM
実用上 Pixel に未知の型を指定することってほとんどなさそうだし、未知の型で 90 度単位以外で使った場合だけ事前条件を満たさないということで実行時エラーで良い気も。
Avatar
rotatedBy90(times: Int)だと?
Avatar
うーん、 rotatedBy90Degrees(times: Int) かなぁ。
2:31 AM
( Swift の API として)なんかあんまり見かけない感じな気が。 (edited)
Avatar
rotate(90x: Int)みたいにできたら分かりやすそうですけど頭に何を付けるべきか思いつかない
Avatar
rotated(by90Degrees: 4, .times) とかね。
2:35 AM
でもあまりに一般的じゃなさすぎて・・・。
Avatar
そのために.timesができるのはちょっとw
Avatar
swift test
4:51 AM
表示がオシャレだ
Avatar
これこの前ここで書いた <# aaa #> のバグの修正かな https://github.com/apple/swift/pull/13480
Explanation: The parser has TokReceiver for recording consumed tokens used by SourceKit. When the parser parses types in editor placeholder (e.g. '<#T##String#>'), it should stop the recording so i...
Avatar
いえ、4.0系ではまだ存在しなかったコードでのエンバグです。
Avatar
別件でしたか
5:23 AM
@rintaro いろいろ試したり読んだりしてるんですけど、 utils/build-script --release --test だと、C++で書かれた unittests たちは実行されない、という理解であってますか?
Avatar
ん、 unittests 内のですか?
Avatar
--test だと testディレクトリのなかのやつは lit で実行されて --validation-test だと validation-testの中は実行されるっぽいけど
5:24 AM
はい。 unittests 内のやつらは、 --build でコンパイルされて実行ファイルとしてのテストランナーが生成されるけど
5:24 AM
build-script の --test からは 起動されない
Avatar
いや、 --test でも実行されると思いますが、ちょっとまってくださいね。
Avatar
あれ、マジカ。可能性として、一瞬でおわってるだけなのかもしれないんですけど・・・
5:26 AM
5:27 AM
cmake --build build/Ninja-ReleaseAssert/swift-macosx-x86_64 -- check-swift-macosx-x86_64 Note that check-swift is suffixed with a target operating system and architecture. Besides check-swift, other targets are also available. Here's the full list: ... SwiftUnitTests: Builds all unit tests. Executables are located under ${SWIFT_BUILD_DIR}/unittests and must be run individually.
5:27 AM
ここも読んで、 besides だから、 check-swift-macos-x86_64 ターゲットだと、 SwiftUnitTestsは含まれてないって意味かと思って。
Avatar
あ〜 testの中のlitから巻き込むようなしかけがあるんですね
Avatar
ですです。
5:33 AM
テスト実行中のプログレスバー下のテスト名出てるところの冒頭に、一瞬かもしれませんが Swift-Unit って表示されると思いますよ。 (edited)
Avatar
なるほど。 このプログレスバーのとこに出たもののログってどこかにありますか?いまも調べ中ですが・・・
5:37 AM
lit.py: /Users/omochi/work/swift-source/swift/test/lit.cfg:331: note: Using test results dir: /Users/omochi/work/swift-source/build/Ninja-ReleaseAssert/swift-macosx-x86_64/./swift-test-results/x86_64-apple-macosx10.9
5:37 AM
これかな、まだ空なんだけd,全部おわったら何か置かれるのか
Avatar
ログは無かったと思いますね。
Avatar
なるほど
Avatar
build-script-v で実行したらプログレスバーじゃなくて1テストごとにターミナル出力されるはず。
Avatar
あ〜 なるほど それが求めていたものだ
5:41 AM
ありがとうございます
Avatar
確かめてないです。出なかったら教えてください。
Avatar
次のタイミングでためしてみます。
Avatar
-v なんてなかった
Avatar
あれ、なんかそういうのはあった気が・・・
Avatar
--verbose-build ってのがあるけど、これはビルドのログの方だけのような。
Avatar
あら
Avatar
--lit-args=-v で。
Avatar
なるほどなるほど
5:56 AM
Current Lexer has a function to skip UTF-8 BOM. But its behavior has some bugs. It skips shebang at the beginning of file, but does not with BOM. A token should be prefix operator at the beginning...
👏 4
5:56 AM
プルリクチャレンジしました
Avatar
3日前くらいの存在型の議論には乗り遅れてしまいましたが、ついにこれを分かる範囲でまとめてみました!koherさんの発言など一部Discordから引用させてもらいました。 https://qiita.com/ukitaka/items/8bcff4348c79d820ba32
iOSのDiscordで定期的にあがる話題として「protocol型の値がそのprotocol自身にconformしていないのはなぜ?」というものがあります。 例えば以下のようなコードです。 ```swift protocol An...
😳 1
👏 2
👀 1
Avatar
@ukitaka ↓の 15 日目のキャンセルを埋めるのが良いかと思います! https://qiita.com/advent-calendar/2017/swift
Taylorじゃない方のSwiftです( ´・‿・`)
Avatar
お、埋めちゃいます😎
👍 1
Avatar
この空きのため、 Swift は Advent Calendar のランキングから除外されちゃってます😭
Avatar
@ukitaka
(openasは失敗しなさそうですが、なぜかif let になっています。。なんでだろう)
ここの T は具体的な型ってことではないですか?
Avatar
具体的な型だと文脈からして役に立たなさそうな気はするけど
Avatar
if let storedInE1 = e1 openas Cat { // storedInE1 は Cat、e1に入ってるのがDogだと取り出せない }
Avatar
それは今でもas? Catでできるしょ
Avatar
Tはopenas構文によって導入される型です。どんな名前でもよいですが、実行時に決まる型です。内部的にはArchetypeTypeとか呼ばれてますね。
3:42 PM
要は存在型の中のXにTという名前を付けて取り出してるんです。
Avatar
この openas と共にその場で作られる型名なんですね。
Avatar
そういうことです!
Avatar
ArchetypeTypeがその場で作るのはokでその辺に存在できないのは、計算量が爆発するかしないかの違いかな
Avatar
うーん実行時に決まる系の型はだいたいArchetypeTypeなので、例えばこういうのもそうですね。なんで普通にその辺にもあるっちゃあります。 func hoge<T>() { let t: T = … // このTもArchetypeType }
Avatar
なるほど
Avatar
@omochimetaru レスついたね。 https://github.com/apple/swift/pull/13483
Current Lexer has a function to skip UTF-8 BOM. But its behavior has some bugs. It skips shebang at the beginning of file, but does not with BOM. A token should be prefix operator at the beginning...
Avatar
お!いい感じ〜〜CIも通った
👏 3
Avatar
https://github.com/apple/swift/pull/13500 いじってる場所が丸かぶりしてたー。
To distinguish \r from \n, added CarriageReturn trivia. Support lexing VCS conflict markers as GarbargeText trivia.
😣 1
Avatar
↑マージされてる!と思ったら rintaro さんが Reviewer だった🙃
Avatar
あw
8:59 AM
CRLFも手を付ける予定でした
8:59 AM
りんたろーさんのTODOコメントがあったから
9:05 AM
https://github.com/apple/swift/pull/13495 ああ、こっちはかぶってコンフリクトになったから
Lexer has two similar methods which are skipToEndOfLine and skipUpToEndOfLine. This PR unify them. The only difference in them are that it will stop at which before or after of newline found, so ad...
9:05 AM
リベースしてってことか
9:05 AM
分けててよかったPR
Avatar
今の僕のPRマージしたら、しばらく別のことやるので、crlf ありがとうございます😀
Avatar
OKです
Avatar
Failingテスト→実装順のコミットだと、通らないコミットが残るのもあり、squashさせていただきました。
Avatar
rintaro merged commit ed58c15 into apple:master an hour ago
本当だ、コミットハッシュが変わってる
9:10 AM
GithubのUIだと一見普通にマージされたように見えますね
9:15 AM
あーだから被らない部分だけちぎって載せ替えればいいのか、わかってきた
Avatar
git rebase 035e478 --onto master でいけないかな
Avatar
Failingテスト→実装順のコミットだと、通らないコミットが残るのもあり、squashさせていただきました。
これって、一個にしちゃうと、失敗することを検証できる瞬間がなくなっちゃうと考えたんですけど、基本的にセットにしたほうがいいんですか
9:24 AM
リベースはうまくいきました。
9:25 AM
テスト通ったらプッシュします・・・(これが大変
Avatar
基本的には セットにしてますね。少なくとも swift のリポジトリでは。公式にドキュメント化はされていないと思いますが、他の PR でその指示は見たことはあります。 (edited)
Avatar
なるほど。じゃあそうします>テスト
Avatar
「失敗することを検証」したいなら、 XFAIL した状態のテストを先にコミットしておくというのが良いと思います。そうすれば「通ったらテスト失敗」という状態になるので。
📝 1
Avatar
あ〜〜。
Avatar
ただ、 googletest で XFAIL できるのかな。。。
Avatar
それで次で成功テストに差し替えるコミットにするのか。
9:28 AM
できなそう?そもそもASSERTだと一個目でこけたら止まっちゃうから全コケも難しいですね
Avatar
最近manglingに関するPRが多くてABIを感じる
Avatar
https://github.com/apple/swift-evolution/pull/754 そういえば cross module 最適化のプロポーザルに @abiPublic というアトリビュートが追加されてた。
Avatar
お! 現行 @_versioned なやつですか
Avatar
そうみたいですね。
Avatar
Swiftって「誰にも呼ばれてないメソッド/参照されてないプロパティ」を見つけて警告だしたりできないのかなー
Avatar
sakusaku_kz - 2017/12/05 はじめまして。未使用のメンバ変数 (グローバル変数?)を検出することは出来ないでしょうか?よく消し忘れてしまうので自動的に見つけられると嬉しいのですが :scream: 自分なりに探したところ、今はその機能がなさそうなのでライブラリやAppCodeのプラグインを使うしかないのかなと思っています https://bugs.swift.org/browse/SR-3721
5:40 AM
この話題 #beginner-help-archived であったけど
Avatar
オウ
Avatar
その時はズバリの答えは無し
Avatar
やろうと思えばできるのかしら
5:42 AM
数学的に無理〜〜〜とかそういうのがあるのかなあとか寝ながら考えたけど
Avatar
やろうと思えばでいえばできるね、C++とかそれよくある
5:42 AM
でもpublicなものは駄目
Avatar
うんうん
5:42 AM
それはそうね。
Avatar
internalとかprivateなら参照されてないから不要って確定するからできる (edited)
Avatar
それってSwiftのコンパイルのフローのなかでいつ誰がチェックするのが適切なんだろう
Avatar
型推論が終わった後でSILを生成する前じゃない?
5:45 AM
いや、SILになってからやったほうがいいのかな
5:46 AM
ロジックとしては未初期化のフィールドを調べるとかと似てるよね
Avatar
あー
Avatar
まあ、未初期化のプロパティは簡単な辞書で実装できるけど、 こっちはでっかいシンボル空間を取り扱う必要があるけど。
5:47 AM
あーdead code検出とかとも関連するね
Avatar
プロトコル絡んでくるとややこしくなったりする?
5:47 AM
プロトコルで強制されてるやつは必須だから警告とかいらんのか
5:48 AM
そりゃそうだ
Avatar
そのプロトコルでせっかく矯正してるけど
5:48 AM
そのプロトコルのメソッドをどこからも呼ばれてない事は
Avatar
Avatar
調べられるかな・・・?
5:48 AM
conformしてる前提だったらまあいけそう
5:49 AM
結構ややこしそうだなあ LLVM-IR になってからのほうが
5:49 AM
メソッドとかなくて全部C言語のグローバル関数みたいなものになってるから
5:49 AM
簡単かもしれんけど、プロトコル互換性とか出てくると駄目か
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
うーん、 filterMap の方がわかりやすかったかも?🤔
Avatar
Sequence.compact()とセットで、と考えるとわかりやすいのかも。
Filtering nil elements from the Sequence is very common, therefore we also propose adding a Sequence.compact() function.
(edited)
Avatar
コンパクションのことかな
Avatar
なるほど。それが導入されるならありですね。
Avatar
compactはfilterのmutating版ってこと?
Avatar
😱 which is not expressible in current Swift syntax.
Avatar
Until we have the missing features, using xs.compactMap { $0 } is an option.
Avatar
extension <Wrapped> Sequence where Element == Optional<Wrapped> { func compact() -> [Wrapped] } こんな感じですかねぇ
Avatar
extension<T> Sequence where Element == T? { func compact() -> [T] { return compactMap { $0 } } }
1:22 AM
同じことを書いてた・・・
Avatar
filter の mutating 版ではないと思います。
Avatar
@omochimetaru 単に nil の要素を落として [T?][T] に変換かと。
Avatar
むむむ?
1:24 AM
あ〜〜。
1:24 AM
クロージャを取らないわけか。
Avatar
generic extension が実現できないと実装できない。
Avatar
あれ、そこジェネリックパラメーターいります?
1:25 AM
あ〜
1:25 AM
Wrappedが Optional<X>だから剥がしたXを表記するのに必要なのか。
1:25 AM
なるほどなるほど
Avatar
where Element == Optional とかも書けないしね
1:26 AM
generic extension じゃなくて parameterized extension か。
1:26 AM
これ普通にほしい機能だから早く実現してほしい。
Avatar
わかる
1:26 AM
ハゲどー
Avatar
ですね
1:30 AM
ジェネリクス系はKotlinだと普通にできる系多いです
Avatar
C# でもできそう。
1:31 AM
higher-kinded type はできないけどね。 < Kotlin (edited)
Avatar
ですね
1:32 AM
ざっくりKotlinはScalaからimplicit系を取り除いたような言語ですね
Avatar
nullable の扱いが違うのも大きいと思う。
Avatar
たしかに。
Avatar
Remove the -enable-experimental-conditional-conformances flag, enabling the feature all the time (and in all language modes). This allows developers to work around any source-compatibility issues d...
Avatar
おおお!
Avatar
swift4.1ってもう配布されてる気がしてたけど勘違いか (edited)
1:34 AM
4.1CC間に合う可能性
Avatar
conditional conformance は一番欲しい機能( parameterized extension よりも)なのでうれしい。
1:34 AM
merged 5 commits into apple:swift-4.1-branch
1:34 AM
すばらしい。春には使えるのか。
1:34 AM
9月になるかと思ってた。
Avatar
おーー
3:47 AM
リリース版のCondConf、ネストしたOptionalがどうなるのか気になる
3:47 AM
問題なのは変換部分だからCondConfは関係ないか、再現しやすくなるだけだ
Avatar
<unknown>:0: error: unexpected warning produced: argument unused during compilation: '-mmacosx-version-min=10.9.0' これが出てテストにコケまくる
Avatar
…rget OS instead of inferring it from SDK / environment The OS version is specified in -target should be used instead of the one in an environment variable / SDK name. rdar://35813850 Different...
Avatar
ほぎゃあ
6:04 AM
あーじゃあ
6:04 AM
clangのとこだけこいつの一個前に戻してみます。
Avatar
お〜いけました ありがとうございます!
6:25 AM
むーそうか swiftリポジトリ以外のところのソースツリーがどうなってるかも調べていかねば
10:22 AM
リバートが投げられてる なるほど、そういう風になるんや
Avatar
"\n\r\r\n\r\r\r\n\r\n\n\n"
5:17 AM
これのパーステスト、通らねえな〜バグってるな〜って思ってたら、バグってるのは自分の目パースでテストコードがおかしくて、ロジックはあってた・・・
Avatar
class MyViewModel {} class MyView { var viewModel = MyViewModel() func something() { var myclosure: () -> () = { [viewModel = self.viewModel] in // 何かしら } } } こういう、クロージャを使ってキャプチャコントロールしてメモリリークしないようにするテク
6:35 AM
これクロージャをジェネリックスにしたくなって詰んだんですが、funcだと同じこと出来ないですよね
Avatar
let viewModel = self.viewModel func myFunc<X>(_ x: X) { print(x) } ではだめと?
Avatar
うお・・・
6:39 AM
ジェネリックラムダ作れないけど確かにインナーfuncならジェネリックにできるの気づいてなかった
6:39 AM
いろいろ考え直さないと・・・
Avatar
出来るには出来るんですが、そうすると広域に要らない参照ができてしまって
6:40 AM
あと最近気がついたんですが、inner funcはオーバーロードできない (edited)
Avatar
Reporter: rintaro Rintaro Ishizaki 👀
6:42 AM
あーーー
6:42 AM
いけそう
6:42 AM
いけます
6:43 AM
カリー化した関数作ってキャプチャしたいものだけ一回ぶち込めばやりたことできそうだ
6:45 AM
func myFunc<X>(viewModel: MyViewModel) -> (X) -> String { // ryaku } // こうして observable.map(myFunc(viewModel: self.viewModel)) // こうじゃ
Avatar
なんかヤバそうな感じのエラー見つけました。↓をコンパイルすると struct Foo<T> { init(_ f: (@escaping (T) -> ()) -> ()) { } } func foo<T>(_ f: (@escaping (T) -> ()) -> ()) -> Foo<T> { return Foo(f) } func bar() -> Foo<() throws -> Int> { let f: (@escaping (() throws -> Int) -> ()) -> () = { _ in } return foo(f) } ↓のエラーになるんですが、同じ型間で "cannot convert" と言ってます。 error: cannot convert return expression of type 'Foo<() throws -> Int>' to return type 'Foo<() throws -> Int>' もっとシンプルにできるかもしれませんが。 Swift 4.0.3 です。
Avatar
お、これは僕も昨日ハマった気がする
🙃 1
Avatar
@tarunon 解決法ありましたか?
Avatar
func bar() -> Foo<() throws -> Int> { let f: (@escaping (@escaping () throws -> Int) -> ()) -> () = { _ in } return foo(f) } この場合、二つ目の @escaping が足りてない? (edited)
8:38 AM
診断エラーメッセージがイケてない。
Avatar
↑型が複雑だと通らなかったので、シンプルに分解してなんとか通しました。解決できたわけではなさそう
Avatar
ん?
Avatar
おおお、本当だ・・・。
12:51 AM
@rintaro ありがとうございます!
🙂 1
Avatar
Errorから任意のProtocolにキャストしようとすると、NSErrorに強制的にキャストされる問題、Swift4.0.3でこっそり治ってるっぽい
10:22 AM
治ってないような…
Avatar
あれ…
11:39 AM
ううん、治ってないですね…
11:39 AM
コメント追記しておこう
Avatar
Existentialのwitness-tableの参照と、classのvtableの参照、どっちのほうがパフォーマンス良いかパッとわかる方いらっしゃいますか? (edited)
Avatar
https://godbolt.org/g/ezbLqV class の方が速そうな雰囲気。
Avatar
5:36 AM
あざす
5:36 AM
コードと中間言語眺めててそんな気はしてた
Avatar
てことは、Protocolを引数に取って~みたいな使い方をしてる場面で
6:40 AM
Classクラスタに置き換えていくメリットは十分にある
6:41 AM
@omochimetaru Classクラスタを使うにあたって、どうしてもinitじゃないといけない、ということはないと思うんだけどinitに拘る理由は何かある?
6:41 AM
Returnする型がSelfにできるのはinitだけなんだけど、Classクラスタでそれは必要ないはず
Avatar
static func でもいいじゃんって事?
Avatar
そう
Avatar
無いんじゃないかな・・・factory init patternは2重alloc問題もあって遅いし
6:46 AM
あ〜
6:47 AM
型名 ( ) で呼び出せるから、initのほうがユーザーの記述量が少ないとか 返り値の型が明確、とかのメリットはあるのかな・・・? static func だと全然関係ない型が返る関数の可能性はあるから。
Avatar
でも結局左辺の型で推論させて.init()ドンみたいなことやるでしょ
6:48 AM
それだとstatic funcで一緒
Avatar
推論でドンの場合はまあ同じだな
6:48 AM
そうじゃない場合に限った話。
6:49 AM
てことは、Protocolを引数に取って~みたいな使い方をしてる場面で Classクラスタに置き換えていくメリットは十分にある
これの決定的な問題点は
Avatar
static func だと全然関係ない型が返る関数の可能性はあるから。
これはコンパイルする言語ならその限りではないとは思った
Avatar
ユーザーが型を追加するときに、親クラスが1つしか設定できない事じゃない?
Avatar
そこでconvertible protocolですよ (edited)
Avatar
> static func だと全然関係ない型が返る関数の可能性はあるから。 これはコンパイルする言語ならその限りではないとは思った
これは Cat.create() -> String とかがありうるから Cat.create() だけからはノーヒントってことね。 Cat() のほうが明確。
6:51 AM
事前に用意するやつはクラス継承にして、ユーザー追加用にはconvertible protocol にするパターンだと
Avatar
static func `init`() -> String (edited)
6:52 AM
こういう脱法コードも存在するし一概には
Avatar
ユーザー追加したものについては、「 convertible protocolから変換したやつを格納するサブクラス」を作ることになって
6:52 AM
その場合について、ディスパッチが vtable + witness-table の2段になる?
6:52 AM
継承先の型パラに焼けるから1段で済むのかな。
Avatar
2段階になる気はするけど
Avatar
Existentialのwitness-tableの参照と、classのvtableの参照、どっちのほうがパフォーマンス良いかパッとわかる方いらっしゃいますか?(編集済)
最初の話題がこれだったんで、2段階になっちゃうのだと微妙かなと
Avatar
考えてるのはRxのDisposableなんで、ほとんどユーザー側では作らないからあんまり気にしなくて良い気はしている
Avatar
なるほど
6:54 AM
自作Disposerで全く同じ事考えた気がする
Avatar
継承側も型パラに焼くようにしておけばwitness-tableへの参照消えるのか?マジ?
Avatar
あのerasureの型パラBoxパターンだと
6:55 AM
convertibleとして扱ってる時は <X> だから実態の型がわかってて、 Box<X> になる時点でもわかってて Box<X> がクラスクラスタに参加してるわけだから
6:55 AM
v-tableの1発 + 具体的なXの型のメソッド呼び出し
Avatar
ほほー
Avatar
で、2発目はwitness-tableは引かないからマシな気がする。
Avatar
Disposableで考えるとassoctypeも存在しないし凄くシンプルにできそうだな
Avatar
↑のProtocolのmethod invocationが遅いかもの話、実測で2-3倍遅いっぽかった
👍 1
Avatar
SwiftとLLVMについて初心者なので質問です。 最適化について調べていて、SILやLLVM IRを見てたら生成されたコードに下記のように main の定義があるんですが、これは SILNM.cpp に定義されてる main funcのことですか? 空のswiftファイルに対して swiftc -emit-sil empty.swift を実行した結果が下記のとおりです。 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>>>): %2 = integer_literal $Builtin.Int32, 0 // user: %3 %3 = struct $Int32 (%2 : $Builtin.Int32) // user: %4 return %3 : $Int32 // id: %4 } // end sil function 'main'
Avatar
Swiftのコードをスクリプトとして実行した場合か、メインファイルの場合はトップレベルに書かれたコードが自動的にmain(つまりエントリーポイント)として扱われてSILがemitされるみたいです。このあたりですかね〜 https://github.com/apple/swift/blob/master/lib/SILGen/SILGen.cpp#L386-L446 https://github.com/apple/swift/blob/master/lib/SILGen/SILGen.cpp#L1279-L1285 https://github.com/apple/swift/blob/master/lib/SILGen/SILGen.cpp#L1390-L1395
swift - The Swift Programming Language
swift - The Swift Programming Language
swift - The Swift Programming Language
Avatar
まさにこの辺ですね!まだソースコードを全部読めてなかったので助かりました。ありがとうございます。
6:34 PM
Kituraを使ってるっぽい。
6:38 PM
自分でデプロイしてライブラリのサンプルをすぐ使ってもらうのもできるかな。UIKit関係ないやつなら。
6:39 PM
IBMのSandboxが終わっちゃうからすごくいいタイミング。
👏 2
Avatar
omochimetaru 1/9/2018 4:19 AM
Proposed Approach: Tighter integration between SwiftPM and Swift The model is that you should be able to say (strawman syntax): import Foo from http://github.com/whatever/mypackage import Bar from file:///some/path/on/my/machine
4:19 AM
クリスラトナーが面白い話してる
4:19 AM
I don’t think the clang modules based approach is a good way to go.
4:25 AM
Swiftのモデルだとclang moduleがベースにあるからスクリプト言語みたいに簡単に相対パスで読み込んだりできないのでスクリプト的な使い方が面倒だなあとgysbを作ってたときに思ってたんだけど
4:26 AM
clang moduleにこだわるというわけでもない話してて驚いた
Avatar
https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md 初質問失礼します 🙇 2017/12/20 にも話題に上がっていた [SE-0187] を読んでいたのですが、
  • `Sequence.flatMap<U>(_: (Element) -> U?) -> [U]
を compactMap という名前にするよ(flatMapも引き続きコンパイルは通るよ) * ついでに Sequence から nil を取り除いて返すSequence.compact() を追加するよ という提案はたぶんわかったのですが、コンパイルエラーが紛らわしい?というモチベーションが(flatMapの挙動が紛らわしいと思ったことがないのもあり)しっくり来ませんでした 
というのも、「StringがCollectionに適合したことによって、Swift 4ではもはやコンパイルできない」と言われている以下のコードが、コンパイル通るんですよね… swift func getNames(people: [Person]) -> [String] { return people.flatMap { $0.name } } ` このProposalってこのコンパイルエラーがどうのこうのっていうのがモチベーションなんでしょうか?それともふつうに(なんかそう書いてあるように見えないんですが)flattenとfilter_map が同じ名前で両方できるのが紛らわしいとか、そういうことなんでしょうか
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 1/9/2018 6:36 AM
えっとまず
6:36 AM
struct Cat { var age: Int = 3 var name: String = "mike" } var cats = [Cat.init(), Cat(), Cat()] let x = cats.flatMap { $0.age } print(x)
6:36 AM
[3, 3, 3]
6:36 AM
これがコンパイルが通っちゃうのが微妙だよね、という話があります
6:37 AM
これは、プログラマーが意図していたコードは正しくは、 cats.map { $0.age } です。
6:37 AM
String から Optional<String> への暗黙変換が発生するせいで、flatMap でも動いてしまっているんだけど、
6:37 AM
実際には全部の要素が .some(String) になっているので、flatMapにする意味がなくって、mapにするべき、という例です。
6:38 AM
で、Swift4でStringがcollectionになっちゃったことによって・・・
6:38 AM
let y = cats.flatMap { $0.name } print(y)
6:38 AM
["m", "i", "k", "e", "m", "i", "k", "e", "m", "i", "k", "e"]
6:38 AM
同じ間違いを、 $0.age じゃなくて、 $0.name で行った場合
6:38 AM
↑のようにもっと悲惨な事になります。
6:39 AM
今度はこれは何が起きてるかっていうと、Collectionを返す関数をflatMap しているので、正しく flatten されてしまっていて
6:39 AM
["mike", "mike", "mike"] になってほしかったのが
6:39 AM
"mike" が ["m", "i", "k", "e"] とみなされて、二重配列がflattenされる挙動になっちゃった。
6:40 AM
想定してるのが「mapしたいのに間違ってflatMap書いちゃった」シナリオだから、
6:40 AM
挙動すらぶっ壊れたってことですね
6:42 AM
で、この問題は、flatMapが受け付けるクロージャが T->[U] と T->U? の2種類のオーバーロードがあることによって、 全てがややこしくなってるから、 後者の T->U? を受け付けるflatMapはcompactMapに名前を変えることにした。
👏🏻 2
😍 2
Avatar
@omochimetaru ウオオわかりやすい…!分かった気がします ありがとうございます! なるほど、Stringを食わせるとそうなるはずなんですね‥たしかに flatMap すると flatten されてそうなるのが確認できました 最初自分が試していたやつなんですが、 swift-evolutionで紹介されてたgetNames() をそのままprintすると ["mike", "mike", "mike"] が出力されてしまうのですが、関数に包まずにそのまま.flatMapするのとこれって何か違うんでしょうか?(なんか初歩的な勘違いをしてるのかもです) struct Cat { var age: Int = 3 var name: String = "mike" } var cats = [Cat(), Cat(), Cat()] let x = cats.flatMap { $0.age } print(x) let y = cats.flatMap { $0.name } print(y) // ["m", "i", "k", "e", "m", "i", "k", "e", "m", "i", "k", "e"] func getNames(cats: [Cat]) -> [String] { return cats.flatMap { $0.name } } let z = getNames(cats: cats) print(z) // ["mike", "mike", "mike"] <- ?!
Avatar
omochimetaru 1/9/2018 7:07 AM
let y: [Character] = cats.flatMap { $0.name } print(y) // ["m", "i", "k", "e", "m", "i", "k", "e", "m", "i", "k", "e"] let z: [String] = cats.flatMap { $0.name } print(z) // ["mike", "mike", "mike"] (edited)
😍 1
7:08 AM
@みなり が書いてるgetNamesは [String] を返す flatMap として推論されてるから ↑の z の例と同じ挙動になってる
7:08 AM
[String] を返すflatMap として推論させるとさっきの$0.ageのパターンの String to Optional<String> の暗黙変換が起きるw
Avatar
@omochimetaru ウオオなるほど!w func getNames(cats: [Cat]) -> [Character] { return cats.flatMap { $0.name } } だと ["m", "i", "k", "e", "m", "i", "k", "e", "m", "i", "k", "e"] になりますね https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md の例だと挙動が壊れないので混乱してしまいました‥ 😅 ありがとうございます!
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 1/9/2018 7:21 AM
proposalが書かれたタイミングの仕様とか今の配布されてるSwiftの挙動とかいろいろ絡むんで文書と一致してないのかもしれませんねえ
Avatar
なるほど
9:00 PM
swift5.0の兆し
Avatar
norio_nomura 1/11/2018 2:28 AM
久しぶりのスナップショットswift-4.1-DEVELOPMENT-SNAPSHOT-2018-01-10-a
Avatar
もしかして Swift って HashDoS の脆弱性がある? $ swift Welcome to Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2). Type :help for assistance. 1> "ABC".hashValue $R0: Int = 4799450059697352752 2> ^D $ swift Welcome to Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2). Type :help for assistance. 1> "ABC".hashValue $R0: Int = 4799450059697352752 2> ^D と思ったけど Linux だと違った。 $ swift Welcome to Swift version 4.0 (swift-4.0-RELEASE). Type :help for assistance. 1> "ABC".hashValue $R0: Int = -7254897348427143244 2> ^D $ swift Welcome to Swift version 4.0 (swift-4.0-RELEASE). Type :help for assistance. 1> "ABC".hashValue $R0: Int = 6530406984862401526 2> ^D Mac / iOS はアプリだしまあ問題ない?
Avatar
omochimetaru 1/11/2018 4:24 AM
Linuxで対策されてることに驚いた
9:11 AM
enum E { case a, b, c, d } var e: E! = .a switch e { case .a: () case .b: () case .c: () case .d: () case .none: () case .some: () } (edited)
Avatar
えなにこれは
Avatar
omochimetaru 1/11/2018 9:11 AM
enum E { case a, b, c, d } var e: E! = nil switch e { // ← ここでクラッシュ!!! case .a: () case .b: () case .c: () case .d: () case .none: () case .some: () }
Avatar
switch e! { ... } こうしたらどうなりますか
Avatar
omochimetaru 1/11/2018 9:12 AM
それは普通にabcdの4通り
9:12 AM
かけばOK
Avatar
ok
9:13 AM
!の型、引数に与えたときの挙動あやしいあやしい
Avatar
omochimetaru 1/11/2018 9:13 AM
明示的にOptionalでやりたいときはどうしたらええんや
9:13 AM
enum E { case a, b, c, d } var e: E! = nil switch e { case .some: () case .none: () }
9:14 AM
↑これでコンパイル通ったし実行時に落ちなかった。
Avatar
こう
9:14 AM
switch e { case .some(.a): case .some(.b): case .some(.c): case .some(.d): case .none: }
9:14 AM
その時はOptionalと一緒
Avatar
omochimetaru 1/11/2018 9:14 AM
じゃあ網羅性はOptional扱いで検査されてるのに case .a が書けるのが一番壊れてるところだな
Avatar
そうすね
9:15 AM
IUOは存在自体が壊れだからあんまり興味なかった (edited)
Avatar
omochimetaru 1/11/2018 9:16 AM
近づきたくないよね。
Avatar
近づきたくないすね
Avatar
case .a が書けるのが変か、最初の @takasek さんのコードで網羅しているとみなされないののどっちかが変だと思う。具体的なユースケースを考えると(というか挙動からしてもアンラップされるんだから)後者が望ましくて、網羅性チェックが壊れてる気がする。
Avatar
T!はTにもT?にも暗黙的に変換されて、評価時はそのどちらかって感じなんで
9:37 AM
switchがT?にシフトしてるのが問題かな
Avatar
omochimetaru 1/11/2018 9:38 AM
var e: E! = nil let x = e ↑のxの式の型は E?
Avatar
T?にシフトしてるならしてるで、case .aは書けないはずなんですよね
Avatar
omochimetaru 1/11/2018 9:38 AM
昔は違ったんだけど最近はすぐ Optional 側に倒されるから
9:38 AM
optionalに行くほうがよろしいと思う
Avatar
var v: UIView! = UIView() switch v.isHidden { case true: () case false: () } プロパティを見る場合はoptional chainされないんだ
9:46 AM
Optionalに倒すんであればプロパティもチェインされるべきですね
Avatar
omochimetaru 1/11/2018 9:47 AM
あーなやましくなってきた さっきのは let 束縛のときだけの話なら、switchの式で使う時は ! に倒れるのでいいのかもしれない
Avatar
おもちさんの言うように「アンラップしたいなら評価時に!をつける」で統一された世界も安全でいいと思います let vv = v! type(of: vv) // __ObjC.UIView.Type switch v!.isHidden { // これもコンパイル通る case true: () case false: () }
Avatar
常にそうなるとオプショナルと同じになるので、どこかしら省略できるケースが残るはずなんですよね。
Avatar
確かに そうなるとlet束縛のときはOptionalに倒れるところからして気持ち悪さ感じる var v: UIView! = UIView() let v1 = v let v2 = v! type(of: v1) // Optional<__ObjC.UIView>.Type type(of: v2) // __ObjC.UIView.Type let h1 = v.isHidden let h2 = v!.isHidden type(of: h1) // Bool.Type 👈 v1がOptionalなら、これもOptional<Bool>.Type になるべきでは type(of: h2) // Bool.Type
10:24 AM
常に評価時はアンラップされる動きなら単純なんですけどね
T!はTにもT?にも暗黙的に変換されて
他にT!がT?として扱われるのって他にどういうパターンあります?
(edited)
Avatar
let a = Int!.some(1) func x(any: Any) { print(type(of: any)) } x(any: a) これもletとほぼ同じな気がしますが
Avatar
それってaに代入するときにaの型がオプショナルにならない?
Avatar
10:36 AM
そだった
10:36 AM
すません、ちゃんとIUOでAnyに渡りました
Avatar
func x2<T>(t: T) { print(type(of: t)) } これならOptional<Int>になった (edited)
Avatar
お、それですそれ
10:46 AM
すみません 🙇
😃 1
Avatar
var a: Int! = 1 func x(_ i: Int) { print(type(of: i)) } func x(_ o: Int?) { print(type(of: o)) // こっちが呼ばれる } x(a) これでもOptional勝ちだった
Avatar
IUOと普通のOptionalの関数はオーバーロードできなかった気がする
Avatar
ほんとだ
10:57 AM
var a: Int? = 1 func x(_ u: ImplicitlyUnwrappedOptional<Int>) { print(type(of: u)) // よばれる } x(a) こんなこともできるんですね
Avatar
コンパイラの気持ちわかんないですけど、 IUOの型を解釈するときって、Optionalで解釈して辻褄合う場合はそうして、ダメならUnwrapした型として解釈する、みたいな流れなのかな
Avatar
SemaレベルではIUO型としてちゃんと扱われてて、 代入とかオーバーロードとかジェネリクス解決とか、都度都度のところでルールが実装されてる
Avatar
都度都度でしたか
Avatar
omochimetaru 1/12/2018 1:57 AM
guard let fd = socketFD else { preconditionFailure("closed") } guard var sa = peerAddress else { preconditionFailure("not connected") } これ今手元にあるコードなんだけど、preconditionって条件式書けるけど、 そのときに Optional unwrapping できないから、guard が必要で渋い
Avatar
kotlinだとスッとできるやつな気がする
Avatar
omochimetaru 1/12/2018 1:59 AM
conditionの代わりに T? を渡して T を返す preconditionの亜種を自作すればいいのかな
Avatar
そんなおもちくんにはこれ! func precondition<T>(_ message: String) -> T { preconditionFailure(message) } let fd=socketFD ?? precondition("closed") (edited)
Avatar
omochimetaru 1/12/2018 2:01 AM
それだと分岐が消えない
2:01 AM
そもそものpreconditionは-Ouncheckedで分岐が消えるのが大事な価値
2:01 AM
(だから↑で僕が貼ってるコードは駄目
Avatar
あーなるほど
2:02 AM
!にメッセージ付けたいねぇ
2:04 AM
(T?,String)->Tの関数作ってinline属性付けるのがいいすかね
2:06 AM
それをオペレーターで実装して!!にする、と
Avatar
omochimetaru 1/12/2018 2:06 AM
func preconditionNotNone<T>(_ x: T?, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) -> T { precondition(x != nil, message, file: file, line: line) return x! }
2:06 AM
これで -Ouncheckedでも preconditionの分岐も消えるし ! も消えるか。
Avatar
fileとlineとるならオペレーター使えないか
Avatar
omochimetaru 1/12/2018 2:06 AM
あ〜
Avatar
@inline(__always)はここでは意味ない?
Avatar
omochimetaru 1/12/2018 2:11 AM
inline(__always) と inlineable の正しい使い分けをマスターしたいな(前者がよくわからん
Avatar
RxSwiftのoptimizationブランチに入ってた
Avatar
omochimetaru 1/12/2018 2:35 AM
この手のアサーションのメッセージ
2:35 AM
「XXがおかしかった」って書く?それとも、「XXであるべきだ」って正当条件を書く?
Avatar
あるべきを書いた方が、正解がわかりやすくなる気がする
Avatar
omochimetaru 1/12/2018 2:51 AM
あ〜たしかに
Avatar
↓に関連して https://qiita.com/omochimetaru/items/c5f0eabde516e4713367 ↓これはできないのか・・・。 var a = [2, 3, 5] swap(&a[0], &a[2]) // コンパイルエラー そして、その代わりに↓があると。 a.swapAt(0, 2) print(a) // [5, 3, 2] (edited)

この記事について

この記事は Swift Tweets 2017 Fall での発表内容を記事の形で再編したものです。 [togetterまとめはこちら](h...
1:23 AM
この swapAt 的なものが型(もしくはプロトコル、 swapAtCollection に実装されている)ごとに個別に必要なのかぁ。うーん。
Avatar
omochimetaru 1/15/2018 1:25 AM
そうですね subscriptアクセスはindexを引数に取るcomputed propertyのようなものなので、内部ではメモリ干渉が起きてないんだけど外側からはわからないから保守的に配列全体を保護しようとして衝突する
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
これ欲しいですね、昔から欲しくて自作ライブラリーに negate() 実装したことある
5:27 AM
Eltaso - This is a framework that contains some convenient methods and extensions for myself
Avatar
値型である Bool でこれができるのが Swift っぽいですよねぇ。
5:28 AM
↓これやりたい。 myVar.prop1.prop2.enabled.toggle()
Avatar
:sorena:
5:30 AM
Discordにカスタム絵文字欲しいw
Avatar
60個まで追加できるんでしたっけ
Avatar
discordlove サーバ管理者がサーバにカスタム絵文字追加して、 Nitroユーザがそれを使える感じなのかな。 (edited)
Avatar
:discordlove:
5:41 AM
ナンダッテー
Avatar
サーバー内のカスタム絵文字ならNitroユーザじゃなくても使えますよ 別サーバーのカスタム絵文字を使う時はNitroユーザーじゃないといけませんが
greenTick 1
Avatar
rintaro先生はNitroユーザーですか
Avatar
お世話になってるので、何がメリットなのかよく知らないけど課金してみました。
😳 1
Avatar
omochimetaru 1/15/2018 6:21 AM
サーバー絵文字は画像ファイル置いてくれれば設定しますよ。
6:21 AM
#zatsu に移動してた
swift 1
swift 2
Avatar
Swift で↓をやりたいときどうしますか? struct Foo { let a: Int var b: Int } var foos = [Foo(a: 2, b: 3)] foos[0].a = 99 // NG foos[0].b = 99 // OK foos[0] = Foo(a: 99, b: foos[0].b) // OK → これを NG にしたい
Avatar
Fooをクラスにしてfoosをletにする
7:43 AM
(not swiftyの絵文字がほしいと思った)
Avatar
Foo をクラスにするのは共有オブジェクトの問題がややこしいので避けたい、という前提だとどうですか?
Avatar
その前提だとそもそもできるんですかね (edited)
Avatar
単純にはできないので、ワークアラウンドとして何かいい方法はないのかなと。 (edited)
7:44 AM
let foos: [var Foo] みたいなのほしい・・・
Avatar
Arrayをラップしたのを作ってsetB(value: index:)を生やす……
Avatar
@t.ae プロパティが N 個だと死にませんか?
Avatar
subscript setつかってfoos.bs[i] = 99みたいな形にもかけそう
7:45 AM
死にますね
Avatar
内部状態としてはArray asと Array bsの2つがあって、アクセス時にFooとしてreadonlyにすればなんとかなるかな?
7:48 AM
ただしfoos[0].b = 99みたいなのはできなくなる
Avatar
foos[0].b = 99 はやりたいとして、ですね。
Avatar
foos.bs[0] = 99 こっちで妥協できませんか?w
Avatar
それはトリッキーすぎて辛いですし、プロパティの数だけ生やさないといけないので・・・。
Avatar
まあそっすね
7:50 AM
classだな
7:51 AM
ArrayはletでFooはclass、aとbをそれぞれlet/varにすればいける
Avatar
↓みたいな構文があればいいのかな・・・。 : の右の letvar を省略時は let ならすべて letvar ならすべて varvar foos: let [var Foo] = ... (edited)
7:52 AM
@tarunon
Foo をクラスにするのは共有オブジェクトの問題がややこしいので避けたい、という前提だとどうですか?
Avatar
使いまわす時にstructに変換噛ませば良いのでは (edited)
7:53 AM
Classだと共有オブジェクトの問題が発生するのはそのとおりですが、それに対しては共有しない、が正解だと思う
Avatar
var foos1 = ... var foos2 = foos1 foos1[0].b = 99 // foos2[0].b も変更される ← これを避けたい
Avatar
Arrayのコピー時にstructに変換してclassに再変換すれば良いので
7:54 AM
まあ一番外側の構造はオレオレで作らなきゃいけないですが
Avatar
foosに追加するインターフェースをstructにすればいいのでは? (edited)
7:56 AM
あ、違うこと考えてました。
Avatar
[swift-evolution] Reminder: Discourse transition starts tomorrow https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20180115/042917.html (edited)
Avatar
アプリあるやん、と思ったけど
4:54 AM
https://itunes.apple.com/jp/app/discourse-app/id1173672076?mt=8 未読管理だけで中身はWebAppだった😫
「Discourse App」のレビューをチェック、カスタマー評価を比較、スクリーンショットを確認、詳細情報を入手。Discourse Appをダウンロードして iPhone、iPad、iPod touch で利用。
Avatar
omochimetaru 1/19/2018 2:34 AM
My "Algebraic Data Type in Swift" slide @TokyoiOSMeetup is now up! https://t.co/E2hwsx8zLz
Likes
146
2:35 AM
おもしろかった
Avatar
わかりやすい
Avatar
We are delighted to announce that the Swift project has completed the process of migrating to the Swift Forums as the primary method for discussion and communication! The former mailing lists have been shut down and archived, and all mailing list content has been imported into the new forum system.
🙌 4
Avatar
http://forums.swift.org/t/proposal-introducing-nonconformingtype-strategies-with-encoder-decoder/8066 任意の型に対するencoding/decoding strategyを入れられるようにしたいとProposal上げたけど、「考慮の上外してるよ、カプセル化を壊してしまうからね」とのこと
Current Encoder/Decoder has a problem that most types (except for Date, Data and Float) have no way to modify encoding/decoding strategies. I want to give them the way. Proposed solution for example of Decoder, struct NonConformingTypeDecodingStrategies { subscript(type: T.Type) -> NonConformingTypeDecodingStrategy? } public enum NonConformingTypeDecodingStrategy { /// Throw upon encountering non-conforming values. This is the default strategy. case throw /// Assume ...
1:40 AM
なるほどと思いつつ、それならinit(from:)の決め打ち実装が現状ちょっと多すぎるんじゃないかなと思った 例に挙げたCGPointとか、デフォではCodableに適合させず、extensionでユーザーにinit(from:)を書かせるほうがよいのでは、という気がします
Avatar
自分でPointとか型を作った方が結局楽な気がする
Avatar
うーん、カプセル化に違反するってのが本当なのか?という気がします。
1:51 AM
デコードについては、イニシャライザがあってそのパラメータがあるんだったら、そのパラメータ相当のデータから生成できて良いのでは?
Avatar
オレオレ型のほうが楽なのは間違いないけど、それは現状追認であって理想じゃないなと
Avatar
で、そのパラメータを取り出せるんだったらエンコードもできそう。
Avatar
例えば座標をFloat配列で出してくるようなAPIがあったとして
Avatar
というか、そもそも単純なデータ構造以外のものを Codable にするのが微妙そう。
Avatar
それはそういう型を作ってCGPointに変換した方が安全だし、元々の型も保存できる
Avatar
仮にある型の実装者が内部構造を考慮した上でエンコード/デコードメソッドを実装できるとして、それが内部構造を知らないと実装不能なデータ構造にエンコード/デコードするなら、それはカプセル化されて隠蔽されたものを外部に露出してるような気が。
Avatar
@tarunon 具体的なデメリットがピンとこないけど何かあります?
Avatar
バイト列にシリアライズ/デシリアライズは OK なら同じかなぁ・・・。
Avatar
@koher プロパティに直接入れるとカプセル化壊れるけど、それは https://github.com/apple/swift-evolution/blob/master/proposals/0189-restrict-cross-module-struct-initializers.md で直るから気にしなくていいはず、ってことですかね
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
ちょっと議論がずれますが、この手のクソAPIはエンドポイント毎に振る舞いが変わってたりして、Codableでは吸収しきれないというのがあります
1:57 AM
そもそもデバッグ時に生の値が欲しい、というケースは往々にしてあって、Pointは単純なのでいらないかな?と思うかもしれませんが
1:58 AM
例えばURLでURL/Path/空文字列/nullなんてこともあり
Avatar
その現実は確かにある
Avatar
そんなものを素直にCodableに詰めて隠蔽すると明晩にはデバッグはできなくなる
2:00 AM
URLは本当にひどい、クエリ部がデコード済みとか、punycodeがデコード済みとか、その組み合わせも
2:01 AM
なんでAPIがクソならちゃんと型作って対処するのが、後々安全だと思います
Avatar
@takasek
プロパティに直接入れるとカプセル化壊れるけど
イニシャライザでってことですか? SE-0189 で禁止されるようなものは元々アンチパターンだと思います。
Avatar
クソAPIは専用の型でも作ってinit(from:)を頑張って書く必要あるのはわかるんですが、 ああそうだ、URL?で空文字が入ってきたときerrorでなくnilにするくらいはstrategyくらいのレベル感で対処できたほうが嬉しいよなと思ったんだった (edited)
2:13 AM
@koher はい、それが今まで出来てしまってたけど、できないようになるので、という文脈での「デコードについては、イニシャライザがあってそのパラメータがあるんだったら、そのパラメータ相当のデータから生成できて良いのでは?」ですよね、という確認です
Avatar
そこまで考えてませんでしたが、そもそもアンチパターンなのでできたとしても気にしなくて良いのでは?ということでした。オリジナルで提供されてるイニシャライザを使う限り問題にならないはずですし。
Avatar
そうですね、納得ですー
Avatar
APIレスポンスによって構造が違う場合、Codableでは吸収しきれないのでオレオレ型を仲介しなきゃいけない ←わかる すべてのAPIレスポンスで構造は揃ってるけど、Swift Standard LibraryのCodableの想定の構造とは違うので、オレオレ型を仲介しなきゃいけない ←なんで? こっちで構造決めさせてほしい というのが自分のモチベーションの根っこだと考えてたらわかりました
Avatar
CGPoint{ "x": 2.0, "y": 3.0 } としたいか [2.0, 3.0] としたいかだけでもブレますしねぇ。
2:35 AM
まあ、 CGPonit に限って言えば僕は CoreGraphics や CGFloat に依存するのが気持ち悪いんでオレオレ Point を作りますが・・・。
Avatar
話のポイントは、 koherさんの仰る「最終的に提供されてるinitを使うのならカプセル化に違反はしないのでは」はあって、 そこを良しとしても、ぼくの👆の話があって、 あとはtarunonさんの「rawValueを残したい」って話は現状のワークアラウンドでできること(そういえば前に https://gist.github.com/takasek/36af17cca297ef73f8bcc1463f9e50c1 でまとめたの思い出した) って感じですね
あと、今日DiscordのSwiftチャンネルでの本題「URL?型に空文字を与えるとdecodeでエラーになるのどうするか」、色々方法出たけど、俺的にはここが結論。 #CodePiece
2:42 AM
CoreGraphic
そこは…そのとおりですねー😅
Avatar
あ、いや、今日tarunonさんが言ってるのはRawRepresentableに限った話ではないのか 元の構造がstructのパターンもある
Avatar
koherさんの仰る「最終的に提供されてるinitを使うのならカプセル化に違反はしないのでは」はあって、 そこを良しとしても、ぼくの👆の話があって、
はい、なのでイマイチ forum の返信がピンと来ないです。
2:55 AM
まあ結局 API を写し取った層を作ってそこからさらに変換とかになることも多いですが(そして、その方が柔軟性は高いですが)、ボイラープレート的でイマイチ感はありますね・・・。
Avatar
どういった形にエンコードされるか、というのを外側から観測してその振る舞いを外側から変えられるようにする、という行為がカプセル化を壊しているという話なんじゃないですかね。
3:01 AM
観測できてしまうのは仕方ないとして(これは @koher さんも書いてるけど)
カプセル化されて隠蔽されたものを外部に露出してる
Avatar
そこが疑わしいと思ってて、僕らはイニシャライザを通してインスタンスを組み立てるわけですが、 JSON をデコードしてイニシャライザを通してインスタンスを組み立てるのと、プログラム中の値からイニシャライザを通してインスタンスを組み立てるのは同じなんじゃないかという気がしてます。 (edited)
3:04 AM
これって、型自身を拡張して Codable にするから違和感があるだけで、 Factory 的なものを介して生成するんだったら違和感がないと思うんですよね。
3:05 AM
あと、そもそも構造が外部に見えるようなシンプルな型( Kotlin で言う data class 的なもの)以外を Codable にするのがアンチパターンな気がしてます。
Avatar
むしろ、型自身が Codable だから、その振る舞いを変えるというのがカプセル化を壊しているように思うんですけど (型の責務を、外から変えてる)。
Avatar
いや、違うのかなぁ。僕のイメージが JSON とか YAML とか DB とかに偏りすぎてるのかもしれません。
3:06 AM
シリアライズの道具と考えると、また違って見えてきますね。
Avatar
ああ、確かに forum を見たときに、シリアライズの道具としてのCodableと考えてるんだなとぼくは思いました。
Avatar
むしろ、型自身が Codable だから、その振る舞いを変えるというのがカプセル化を壊しているように思うんですけど (型の責務を、外から変えてる)。
これって Comparable をソートするときの挙動を↓でカスタマイズするのと同じじゃないですか? https://developer.apple.com/documentation/swift/array/2296815-sorted
Avatar
シリアライズの道具としてCodableが作られたけど、実際によく使われるシーンとしてはJSONのような汎用の形式との相互交換が多く、むしろそっち方面で人気があるから、ややこしいことになってる気がする。
Avatar
omochimetaru 1/23/2018 3:08 AM
シリアライズの道具としてCodableが作られたけど、実際によく使われるシーンとしてはJSONのような汎用の形式との相互交換が多く、むしろそっち方面で人気があるから、ややこしいことになってる気がする。
これめっちゃ思う。
3:09 AM
Encoder/Decoderのインターフェースはデータ構造にたいして抽象的に設計されているのに、 結局JSONの事考えながらやってるから、
3:09 AM
余計に抽象化されててAPIがわかりにくいって感じることが多い
3:09 AM
この前 JSONの配列に1:1対応する型を作ろうとして、 singleValueContainerにたいして decode([Hoge].self) みたいに書いてて
3:09 AM
全然わからなくてワロタ
Avatar
うーん、やっぱカプセル化うんぬんは変な気がして、 Encoder/Decoder は最終的なフォーマットによらない抽象構造との間の動作を規定するので、その抽象構造の先の具象構造が [x, y] だろうが {"x": x, "y": y} だろうが構わないはずなので、そこをカスタマイズしてもカプセル化は壊れない気が。 (edited)
Avatar
Coparableのカスタマイズの方は、Arrayに生やしたメソッドだから、別にカスタマイズできていいんじゃないですか。Comparableなオブジェクト自体の比較動作を変えたりはしてないので。
3:14 AM
あ、そうか。たしかに、Encoder/Decoderの振る舞いを変える提案なんだから、Codable自体の動作は変わらないですね。言われてみれば確かに。
3:15 AM
カプセル化されているのが何なのかよくわからなくなってきました 😐
🤔 1
Avatar
本当にシリアライズの道具だとしたら、dateDecodingStrategyとかも本来許してはいけなくて、シリアライズ方法ごとに型を作って対処すべきですよね この間、UserDefaultsにdateをもつ型をエンコードして突っ込んで、それをデコードしたらstrategyが違って危うくバグるところでした forumに特別扱いの理由は書かれていましたが、やっぱり中途半端な感じがします
Avatar
omochimetaru 1/23/2018 3:33 AM
dateDecodingStrategyとかも本来許してはいけなくて、
この部分については
3:33 AM
「JSONEncoder」固有だから良いんだ って言ってました
3:34 AM
(よくわかってないけど)
Avatar
僕が英語をちゃんと読めてないのかもしれませんが、カプセル化が Codable な型のことを言っているのであれば、別に JSONEncoder/Decoder のレイヤーでカスタマイズできてもカプセル化には問題ないような気がしますね。 (edited)
Avatar
ああ、混乱してました そう、シリアライズの道具なのはCodableであってCoderではない…から…えーっと、もう一度forum読んできます…
Avatar
We did this for Dates and Data specifically because they are 1. Incredibly common types, which are likely to have the same representation across your entire payload, because 2. Specific format requirements are likely controlled by whatever software is running on a server, and for those very integral types, the server is likely opinionated/has specific requirements いまいちよくわからない 「DataとDateに特別にstrategyが許されるのは、全payloadでサーバの統制の元、同じ表現が使われがちだから」って意味であってますか? であれば、それはstrategyではなく、init(from:)の決め打ち実装をなくしてユーザーにextensionで書かせるべきなのでは
Avatar
payload全体を通して同じ表現が使われがちだから、ということでしょうね(ほんとにそうなの?という疑問はありますが)
4:49 AM
あと、Incredibly common typesだから、というのも重要なのかも。
Avatar
ああ、なんとなくわかってきたかもしれません。 ←いや、わからなくなってきた 🤔 (edited)
Avatar
彼らの言い分に納得できたわけではないですが、なんとなく言い分がわかってきた気がします。
6:24 AM
Proposalの方法では例えば CGPoint の表現を変えることができるけど、それは内部で CGPoint を持っている別のstructの表現にも影響を与える。でも、そのstructは CGPoint が配列表現でエンコードされているという想定で実装されているかもしれないので外から挙動を変えるのはよくない(←ここ、どういうときにそんなことがあるのかぼくは今ひとつ納得いかない)。だからそういうのは認めたくない。
6:25 AM
だけど「JSONでは」日付とデータの決まった表現がないにも関わらず、現実的にはかなり一般的に利用されていて、表現のブレを吸収できる何かを用意しないと JSONDecoder が使えない物になるから、例外的にそれを提供した、ということかと思いましたがどうでしょう。 (edited)
Avatar
でも、そのstructは CGPoint が配列表現でエンコードされているという想定で実装されているかもしれないので外から挙動を変えるのはよくない(←ここ、どういうときにそんなことがあるのかぼくは今ひとつ納得いかない)。
ひとつの JSON 等の中で同じ型にデコードされるものが別の形式で表現されてるのはどうにもならない気が・・・。
6:39 AM
たとえば、 struct Line { var point1: CGPoint var point2: CGPoint } を作ったとして、 LineCGRect で内部の CGPoint の表現を一つの JSON 上で変えようというのはさすがに JSON が壊れすぎかと思います。 (edited)
6:41 AM
↓とかはひどい気が。 { "rect": { "origin": [2.0, 3.0], "size": [100.0, 200.0] }, "line": { "point1": { x: 0.0, y: 0.0 }, "point2": { x: 100.0, y: 100.0 } } } (edited)
Avatar
It’s common to include types which are not your own in payloads
それに関しては外部システムからの JSON をそのまま要素として含んでるということがよくある。というのがそれに対する反論みたいですが、 Date こそその可能性が多いような気がします。
(edited)
Avatar
抽象レベルが違っていて、サーバー側では別の構造だけどiOSでは同一の構造に丸めたい、とか有り得そう
Avatar
omochimetaru 1/23/2018 6:42 AM
対象のフォーマットによっては、 <Point x=1, y=2> と <Line x1=1, x2=2, y1=3, y2=4> みたいにしたい とかあると思います。
Avatar
なんかそもそもプリミティブの値を適当な構造に変換したいっていうのが業だよなぁという気がしている
Avatar
omochimetaru 1/23/2018 6:42 AM
Swift上のstored propertyのツリー構造と、シリアライズ先のデータ構造が対応取れない事もありえる。
6:43 AM
シリアライズしたい話しと、特定のフォーマットに書き出したい話が混ざっちゃってるんだとは思う。
Avatar
外部システムからの JSON をそのまま要素として含んでるということがよくある
なるほど。これは辛い、けどもうカプセル化うんぬんの話じゃなくて、それは別の型にマッピングしないとどうしようもない気がします・・・。
Avatar
いずれにしても、トップダウン(root要素から) デコードしていくので、デコーダー全体のデフォルトとしての strategy を設定できるのは個人的には良いと思いますけどね。
6:44 AM
例外的なのがあるなら、一つ上の親要素の デコーダで吸収すれば良いし。
Avatar
@omochimetaru
対象のフォーマットによっては、 <Point x=1, y=2> と <Line x1=1, x2=2, y1=3, y2=4> みたいにしたい
これは単にそういう風に Line のデコード/エンコードを実装すれば良いのでは?
Avatar
omochimetaru 1/23/2018 6:45 AM
ああ、同じ型だけど文脈で変えたいという話なのか
Avatar
@rintaro そうですよねぇ。
Avatar
ぼくも、そもそものリジェクト理由のカプセル化うんぬんのところが納得いかないんですよ。
Avatar
みんなの意見が概ね同じな気がしますね。
Avatar
覆すには親要素の init(from:) で吸収できない、または著しく不便になる例を示すしかないでしょうねぇ。
Avatar
今ってその型自体のストラテジーを変えたいってことなんじゃないですか?
6:55 AM
親で吸収しようとしても、 CGPoint がたくさんの型で使われていて、そのデフォルトの挙動と違う風にデコード/エンコードしたいときに全部親側で吸収はさすがに不便かと。
Avatar
omochimetaru 1/23/2018 6:56 AM
あ〜それもめちゃめちゃ困る時がある
6:56 AM
CGPointだけ変えたいんだけど、他にも var name: String, var age: Int みたいに
6:56 AM
デフォルト戦略でいい(自動生成で良い)stored propertyの部分まで
6:56 AM
encodeとdecodeのボイラープレートを書かないといけなくなっちゃう。
6:57 AM
(しょーがないからその型用のCGPointをラップした型を作って getter/setterでCGPointに見せかけることになる (edited)
Avatar
the recommended approach ... is to write an adapter type which does have the format you’d like to use ... Is there a use-case that this approach doesn’t meet, though?
なんで、面倒な例を示してあげないと議論が進まない状態と思います。
Avatar
omochimetaru 1/23/2018 7:04 AM
import Foundation var json = """ { "a": "/home/omochi/temp" } """ struct Config : Codable { var a: URL } let decoder = JSONDecoder.init() let config = try decoder.decode(Config.self, from: json.data(using: .utf8)!) print(config.a.path) print(config.a.isFileURL) let encoder = JSONEncoder.init() encoder.outputFormatting = .prettyPrinted let j2 = try encoder.encode(config) print(String(data: j2, encoding: .utf8)!) var b = URL.init(fileURLWithPath: "/home/omochi/temp") print(b.isFileURL) print(b)
7:04 AM
今手元で踏んでるのがこれ
7:04 AM
config.a.isFileURL が true になってほしいけど false になっちゃう。 b は true だけど file:/// 形式だから嫌。
7:07 AM
(本題のフォーラムの方はまだ読んでないです、ずれてたらすいません) (edited)
Avatar
その例は URL じゃなくて独自型作ってラップしようって言われて終わっちゃいそう
Avatar
Thank you for your reply!
they have built-in assumptions about how their types are represented
Yes, they have assumptions about the payload structure. However, sometimes it differs from built-in structure provided by Swift standard library, like the example of CGPoint .
Dates and Data specifically because they are ... likely to have the same representation across your entire payload
I agree. Not only Date and Data , but also all types are likely to have same representation across entire payload. The types indicate their only one representation by conforming to Codable . The current problem is that, when it differs from assumption, there is no way to adopt "really" assumed format instead of built-in format. So I realized that introducing strategies is not the best way for my motivation. A better way is to
  • remove built-in Codable conformance from some types ( Data , Date , CGPoint and more).
  • let developers define their own extension Foo: Codable to conform their "real" format.
What do you think of this idea?
8:23 AM
返事を考えたけどStrategyの話ではなくなってしまった
8:24 AM
(見当違いなこと言ってないでしょうか…)
Avatar
Kishikawa Katsumi 1/23/2018 8:26 AM
元々の要件は任意のプロパティにDateみたいに変換ロジックを簡単に(initのオーバーライドよりも。全部のマッピングを変更したいわけじゃないので)提供したい、っていうことだと思ってたんですけどあってます?
8:27 AM
あってるかっていうのは私の認識がそれであってるか、という質問です。
Avatar
strategyとして提供する場合はそういう要件になりますね
8:28 AM
💭 自分のモチベーションとしては、 APIレスポンスによって構造が違う場合、Codableでは吸収しきれないのでオレオレ型を仲介しなきゃいけない ←わかる すべてのAPIレスポンスで構造は揃ってるけど、Swift Standard LibraryのCodableの想定の構造とは違うので、オレオレ型を仲介しなきゃいけない ←なんで? こっちで構造決めさせてほしい という点のほうが強いですが (edited)
Avatar
Kishikawa Katsumi 1/23/2018 8:29 AM
それは要求としては理解できますし、そういうことがあれば便利な場面があるのも理解できます。(私の意見としては標準ライブラリに入れるほどではないと思うんですが、ただその線引きはDate/Data/Floatは入っていた方が便利と判断されて入ってるので、どっちにもたおれうると思います)、
8:29 AM
とすると、
8:29 AM
remove built-in Codable conformance from some types ( Data , Date , CGPoint and more).
8:29 AM
この辺の話に広げるとたぶん
8:29 AM
話が違う方向に行っちゃうんじゃないでしょうか。と思いました。
Avatar
- let developers define their own extension Foo: Codable to conform their "real" format.
だと、デコーダ毎からタイプ毎(つまりアプリケーション毎)になって範囲が変わってしまうので
8:30 AM
なかなか難しいですね。
Avatar
Kishikawa Katsumi 1/23/2018 8:30 AM
私がこの話をするなら、 > 線引きはDate/Data/Floatは入っていた方が便利と判断されて入ってるので
Avatar
なるほど。やるとしたら別スレッドで議論すべきこと、ですね
Avatar
Kishikawa Katsumi 1/23/2018 8:30 AM
^ まずはここを広げていくところから始めると思います。
8:31 AM
URLはできた方がいい、Decimalを扱えた方がいい、
8:31 AM
などというのはけっこう理解してもらいやすいと思います。 (edited)
8:33 AM
例えばPoint型とかはそれよりはちょっと離れていて、かつ、あまり実感として他の人に便利さが伝わりにくいので議論するならいいけど、要求を通すにはまとまりにくそう、と思います。Point型に近いところだと緯度経度とかの方がまだ伝わるかと。
8:35 AM
URLはカスタムできないけどJSONDecoderでサポートされているマッピング型なのでまたややこしくなっちゃうかな。。。
8:39 AM
ともかく、CodableやJSONDecoderを入れるか入れないかという時期の話ではないので、具体的な問題から出発してDate/Data/Floatに許されてる部分を他の型にも広げるのがいいんじゃないですかね。一旦広がったら、そのあとうまくいってるから汎用的な仕組みを入れてもいいんじゃないか、という提案に繋げると。
Avatar
そうですね、forumの返信でも特定のユースケースを求めているし、個別の型ごとに議論を進めていくのがよさそうですね。
Avatar
Kishikawa Katsumi 1/23/2018 8:47 AM
私としてはさっきの議論でもそこそこ色々な話が出たので、リモートかつ英語のコミュニケーションというのを考慮して、XXXというほとんど基本型といってもいい型についてxxxDecodingStrategyというのを追加するというのはアリなのかナシなのかというところをまず話した方がいいと思うんですよね。
8:48 AM
そこにあまり乗り気でないとするとそのままで要求を通すのは難しいので別のアプローチが必要になります。
Avatar
話のしかたを色々考えてみましたが、とりあえず最初には皆が引っかかってた「カプセル化違反」について確認して、求められてた「面倒な例」をひとつ挙げるだけにとどめ、forumにリプライ投げました。皆様ありがとうございますー。
xxxDecodingStrategyというのを追加するというのはアリなのかナシなのか
についての提議は話が膨らみすぎそうなのでまだ触れないでおきましたが、もし気が向いたタイミングで助太刀していただける方いらっしゃったら嬉しいかもです 😖
(edited)
Avatar
あと夕方の @omochimetaru さんのやつは、こういうんじゃ嫌なんですか? struct FileURL: Codable { let url: URL init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let path = try container.decode(String.self) guard path.first == "/" else { throw DecodingError.dataCorruptedError(in: container, debugDescription: "絶対パスにすること") } url = URL(fileURLWithPath: path) } func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(url.path) } } struct Config : Codable { var a: FileURL } let decoder = JSONDecoder.init() let config = try decoder.decode(Config.self, from: json.data(using: .utf8)!) print(config.a.url.path) print(config.a.url.isFileURL)
Avatar
@takasek 実際、それになってるけど a.url をいちいち書くのが面倒です
Avatar
:sorena:
Avatar
var a private にしつつ URL の computed property を生やす方法もあるけどそれも面倒だし、メモリや計算効率的にも無意味なオーバーヘッドがある。(最適化で消えている可能性はあるけど) (edited)
Avatar
Kishikawa Katsumi 1/23/2018 10:59 AM
私はこの例は単純にStringで受けて適宜使うタイミングでURLにする方がいいと思うんですよね。JSONDecoderのURLはファイルURLを想定してないと思います。
☝ 1
11:00 AM
URLクラスの問題ともいえるけど。文字列からFoundationのURLへのマッピングは自明ではないので、無理にマップしようとしない方がいいと思います。 (edited)
Avatar
文字列型を露出させるとその変換をサボって文字列のまま取り扱う恐れがあるのが嫌なんですよね URL型じゃなくてFilePath型があったらいいので、自作したものとかもあるんですが、 Foundationに入ってるのは楽なので使いたくなる・・・
Avatar
Kishikawa Katsumi 1/23/2018 11:12 AM
厳格にしたいとか誤操作を防止したいという目的にはFilePath型を使うのが正解だと思いますね。FoundationのURLにしてもそんなに効果ありますかね?とりあえずStringで持つことについてはSwiftのStringはNSStringと違ってパスを操作するメソッドとか無いので、普通は適宜URLを使わないですかね。
11:13 AM
どっちかだと思います。なんとかしてURLで保持しようというのは問題を難しくしてると思います。
Avatar
appendingPathComponentとかpathExtensionとか便利ですね 都度変換はめんどくさくなって、直接 + “/temp” とかやっちゃって、そのうちスラッシュの取り扱いポリシー間違えて死ぬのを過去に何度かやったので、常にパス用の型で見えるようにしたいです。 Stringで保持してプロパティで都度変換するのがバランス良いかもと思えてきました
11:20 AM
プロパティの都度変換だとjsonのキーとプロパティ名の対応がズレるのを諦めるかか、CodingKeysを手動定義するか、そのどちらかの苦しみがあるんだった。迷う・・・
Avatar
Kishikawa Katsumi 1/23/2018 11:24 AM
JSONや外部のデータとネイティブオブジェクトのマッピングは、できるだけマッピングを素直に保って自明な状態にしておく方がおそらく良いと思ってるんですよね。
Avatar
DTOとして割り切って、Modelにはそこからさらに変換かけるイメージでしょうか?
Avatar
Kishikawa Katsumi 1/23/2018 11:40 AM
はい。Swiftだとたいていは適当なfunctionで最初はよくて、大きくなってきたら適当なPrivateのStructにして、もっと進んだら独立したデータ型にしてファイルも分けてテストを書いて、って感じですかね。
Avatar
僕も実際はコードベースが育ってくるとそうやって分けてますね
11:49 AM
Swiftだとpropertyの初期化の網羅チェックが入るから、そういう変換を書く時にフィールドの渡し漏れなどが無いので助かる
Avatar
CodingStrategyの話って、もしかして https://github.com/norio-nomura/ObjectEncoder/pull/11 が元になってるのかな?
Add ObjectEncoder.EncodingStrategy and ObjectDecoder.DecodingStrategy that creating strategy Add ObjectEncoder.encodingStrategies and ObjectDecoder.decodingStrategies th...
Avatar
おお、nomuraさんも似たことをやってらした
Avatar
あ、似てただけですか。失礼しました。
Avatar
いえいえ
12:30 PM
ObjectIdentifier型、知りませんでした 標準であるんですね
Avatar
僕のは、DataDateも全部ひっくるめてのStrategy実装になってます。 (edited)
12:31 PM
var encoder = ObjectEncoder() encoder.encodingStrategies[Date.self] = .iso8601 let encoded = try encoder.encode(Date(timeIntervalSince1970: 1000)) encoded == "1970-01-01T00:16:40Z" // true var decoder = ObjectDecoder() decoder.decodingStrategies[Date.self] = .iso8601 let decoded = try decoder.decode(Date.self, from: encoded) decoded == Date(timeIntervalSince1970: 1000) // true
Avatar
extension ObjectEncoder.EncodingStrategy where T == Date みたいな形でメンバ生やしてるんですね
Avatar
JSONEncoder, JSONDecoderに備わってるStrategiesのスーパーセットにしてたはず。
Avatar
ちょっと確認なんですが、 @takasek さんの提案は、 JSONEncoder / JSONDecoder に対する機能追加ってことですよね? それとも、 Encoder/Decoder 一般の話として提案してますか?
2:31 AM
ぼくは前者(JSONだけ)と思ってたんですが、forumをよく見たらJSONはただの例にも見えたので。
Avatar
現在の PropertyListDecoder には(必要なかったからというのもあるでしょうが)strategy系のプロパティはないので、strategy系のやつはJSONをpayloadにする場合のオプションだと思います。本来、日付やデータはJSONには入れられないはずなので、原則的には、例えば日付ならDate型の init(from:) に任せるべきなんだと思います。
2:52 AM
そこを例外的に認めているのは、たぶん、世の中に存在するJSONが日付を扱っていて、サーバーサイドでも日付型を変換してJSON化する方法が一般的に取られていて、その例外を認めてあげないと、Swiftとしての魅力がなくなってしまうからかなあと思いました。だから、一般的に使われている代表的な変換方法をstrategyとして提供しているのだろうと。
2:57 AM
もしこの想像が合ってるなら、JSONで対応してあげないとSwiftの魅力が半減するような「一般的な」型を例としてあげないと、納得してくれないように思いました 🙄
Avatar
AとBがあって、それぞれnilの可能性があるが、両方同時にnilであることは有り得ない
7:31 AM
↑を表現する一番スッキリする方法
7:32 AM
enumで3ケース書く方法しか思いつかなかった。
Avatar
omochimetaru 1/25/2018 7:32 AM
3値論理だ
7:32 AM
ちょっと違うか
Avatar
AとBがあって、どちらか存在する、ならenumで超すっきりなんだけど、
7:33 AM
↑↑↑の例はなんかモヤ感がある
Avatar
omochimetaru 1/25/2018 7:33 AM
enumのOptional?
7:33 AM
あ、ぎゃくか。
7:33 AM
両方nilは無いのか。
Avatar
素直にenumで表現するとこう enum X<A, B> { case both(A, B) case a(A) case b(B) }
7:34 AM
やっぱこれしかないかなぁ
Avatar
omochimetaru 1/25/2018 7:34 AM
素直に struct にして両方nilも出ちゃうけど諦めよう
Avatar
ええーーー
Avatar
Kishikawa Katsumi 1/25/2018 7:35 AM
素直に structにしてinitで制限したらいいんじゃないかなあ。
Avatar
omochimetaru 1/25/2018 7:35 AM
使う側で両方nilのケースには fatalError("never this")
Avatar
private プロパティにしてアクセサ付けるのが素直だと思います。
Avatar
これ考えてる理由としては、Errorの合成なんですが(実際にはプロダクトではもう必要なくなったけれども興味で)
7:36 AM
処理Xと処理Yを合成する時に、それぞれ並列で走らせた結果として、それぞれのエラーを合成する時に
7:36 AM
合成が発生するからにはどちらか一方は必ず発生しているという状況になって
7:36 AM
あーーー
7:37 AM
ErrorをOptionalにすれば素直にOptionalの掛け算でいいんかな (edited)
Avatar
omochimetaru 1/25/2018 7:37 AM
それだとnil nil があるんじゃ?
Avatar
Optionalの掛け算だと
7:38 AM
errorAorNil.flatMap { x in errorBorNil.map { x * $0 } } これでerrorAorNilかerrorBorNilがnilだと消えちゃう (edited)
7:39 AM
@rintaro
private プロパティにしてアクセサ付けるのが素直だと思います。
これはstruct enum どっち前提ですか?
Avatar
omochimetaru 1/25/2018 7:42 AM
Errorの話だと、 ErrorA , ErrorB, CompositeError<ErrorA, ErrorB>
7:42 AM
みたいにできそうだけど・・・
Avatar
これはstruct enum どっち前提ですか?
struct です。
Avatar
残念ながら今Result文化圏に住んでいまして。。。
Avatar
omochimetaru 1/25/2018 7:44 AM
結局そこで3択enumが必要になるか。
Avatar
エラーが発生しても後続の処理は続行して行い、全てのエラーを合成する という処理が必要になって
7:45 AM
合成可能なエラー型を作ったはいいが、これを合成するいい方法を思いつかなかった。結局コレ自体はいらなくなったけど
7:45 AM
ベストプラクティスを今に至るまで思いつかないのでここに来た、って感じす
Avatar
素直に struct にして両方nilも出ちゃうけど諦めよう
これがありなら Either<T, U>(T?, U?) で表せばいいよねっていうのを認めることになってしまう気が。
👆 1
Avatar
omochimetaru 1/25/2018 7:47 AM
それは Eitherの文脈で TかつU を許容してるので
7:47 AM
罪の数が2倍多い
7:47 AM
今回なら罪状1件で済む
Avatar
ワイ潔癖症一寸の罪も許さず
Avatar
(T?, U?) | | T | N | |:-:|:-:|:-:| | U | o | o | | N | o | o | (edited)
7:50 AM
Either<T, U> | | T | N | |:-:|:-:|:-:| | U | | o | | N | o | |
7:50 AM
今作りたいもの Foo<T, U> | | T | N | |:-:|:-:|:-:| | U | o | o | | N | o | | (edited)
Avatar
あー
Avatar
omochimetaru 1/25/2018 7:51 AM
そうそう、罪状の数はそういうこと
Avatar
Optional2引数の合成関数を作るのは、綺麗な世界じゃないけどそれなりに欲しいものは出来る気がしてきた
7:51 AM
flatMap, ?? のいずれも出来ない事を実現する関数
7:53 AM
extension Optional { func merge(with other: Optional, f: (Wrapped, Wrapped) -> Wrapped) -> Optional { if let x = self, let y = other { return .some(f(x, y)) } else { return self ?? other } } }
7:53 AM
これだ!
Avatar
omochimetaru 1/25/2018 7:53 AM
ああ、何を言いたいかわかった
Avatar
Either は sum type だけど or じゃなくて xor なのか。
Avatar
omochimetaru 1/25/2018 7:54 AM
「両方ある」のは一瞬でよくて、すぐ畳み込んでも大丈夫なケースなのね。
Avatar
そう
Avatar
今作りたいのは xor じゃなくて or
Avatar
いや今回はたまたまそうだったけど常にそうとは限らない
Avatar
@tarunon どっちの返信がどっちに向けたものでしょう?? (edited)
🙇 1
Avatar
両方おもちあてです
👍 1
Avatar
omochimetaru 1/25/2018 7:59 AM
常にそうとは限らないならやっぱり一般論としては3case enumがいるよね
Avatar
とりあえず3case enumを作るしか無さそうだというのは理解してきた。それって一般的な構造として名前ついてるのかな。
Avatar
Either<(A, B), Either<A, B>>
Avatar
omochimetaru 1/25/2018 8:01 AM
聞いたこと無い。 いなみせんせいを呼ぼう。
Avatar
Either<(A, B), Either<A, B>>、Typealiasがほしいw
8:02 AM
確かにそうだ
8:02 AM
其の型であってるんですよ、それだ、それはスッときた
Avatar
omochimetaru 1/25/2018 8:03 AM
Either3<(A, B), A, B>
8:03 AM
Either3<A, B, C>Either<A, Either<B, C>> と同型
Avatar
Either<(A, B), Either<A, B>> 、 sum type と product type が組み合わさって↓な世界だ。 https://speakerdeck.com/inamiy/algebraic-data-type-in-swift
Avatar
omochimetaru 1/25/2018 8:04 AM
↑これ本当にメンタルモデルが一回り整理されて良かった
Avatar
@inamiy
8:04 AM
(来てくれるかな…)
Avatar
scalaz - An extension to the core Scala library for functional programming.
👀 1
😀 1
Avatar
omochimetaru 1/25/2018 9:04 AM
おお〜 this, that, both
Avatar
処理Xと処理Yを合成する時に、それぞれ並列で走らせた結果として、それぞれのエラーを合成する時に合成が発生するからにはどちらか一方は必ず発生している
ただscalaだとこういうケースであればNonEmptyListっていうのを使うことが多い感じします。(もちろんErrorAみたいな具体的な型はなくなってしまうけど。。) http://eed3si9n.com/learning-scalaz/ja/Validation.html
Avatar
関連して雑談的に思ったんですが、 T|UTU のどちらか一方しか許さないのに、 t|utu の両方を許容していて、 T|U はむしろ t^u 的で T^U なんじゃないかという気が。
Avatar
omochimetaru 1/25/2018 9:10 AM
^ は指数記号じゃなくてXOR記号?
Avatar
うん
9:10 AM
自然言語の or って曖昧さがあるよなぁと思ってたけど、これまで T|U にそんなことを考えたこともなかったってことは、頭が自然言語に相当毒されてる・・・。
Avatar
omochimetaru 1/25/2018 9:11 AM
たしかに
Avatar
代数的データ型の sum type は排他的だけど論理和は排他的でない?そこは xor と対応しなくて良い??
Avatar
omochimetaru 1/25/2018 9:12 AM
和集合って考える時に
9:12 AM
タプルにならなくないですか?
Avatar
集合じゃなくて論理の方
Avatar
omochimetaru 1/25/2018 9:13 AM
データ型の 線形代数的に考えてる時は集合論がベースにあるんじゃないですかね
Avatar
∪じゃなくて∨
9:14 AM
それはそうとして、論理和と排他的論理和と和集合とsum typeの関係はどうなってるんだろう?と。 (edited)
Avatar
omochimetaru 1/25/2018 9:15 AM
ふーむ
Avatar
なんか数学的な関係がありそうだけど、 sum type は排他的なのが気になる
9:17 AM
また @Taketo Sano さんの意見が聞きたいけど、最近ここにいなさそう💧
Avatar
正月明け以降しばらくは全体的に過疎ってた感
Avatar
英語だと sum type だけど日本語だと直和型だから、その「直」の部分に意味があるのかな?
9:23 AM
和型でないのは。
9:26 AM
@taketo1024 突然質問すみません。Discordのios-developers-japanで話してたんですが、直和型と論理和と排他的論理和の数学的な関係がどうなってるかご存知でないでしょうか?Either<T, U>がTとUのどちらかしか許さないのは、論理和よりむしろ排他的論理和に近い気がするのですが。
👀 1
Avatar
うーん、Eitherは(排他的論理和じゃなく)論理和でいいんじゃないかなあと思いました。その理由 https://gist.github.com/hironytic/9cb2f09d22a615dd26c043589c7a4b31
Eitherは論理和でいいと思う理由
Avatar
どうもです🙇‍♂️ (edited)
2:21 PM
「代数的データ型」の代数構造について何も知らないのでちゃんとしたことは言えませんが、直和・直積は圏論による定式化があって、考える圏によって定義は色々と変わります。 (edited)
2:22 PM
例えば集合の圏だと、直和は非交和 X ∪ Y で直積は X×Y。 (edited)
2:23 PM
有限次元ベクトル空間の圏だと直和と直積は同じで X × Y(無限次元になると別) (edited)
2:27 PM
半順序集合自体を一つの圏と見ることもできて、この場合の積は ∧、和は ∨。ブール代数(ブール束?)との関連はこの辺りにあるんだろうと思います(詳しいことは知りません) (edited)
2:28 PM
代数的データ型も恐らく何らかの方法で圏と見なすことができて(型を対象、関数を射と見るのかな…?)、そこでは enum が直和、struct が直積に対応するものになるのだろうと思います。 (edited)
2:30 PM
なので数学的関係については「圏論の和・積」を通してあることになるんだと思います。もっと直接的な関連もあるのかも知れませんが分かりません🙇‍♂️ (edited)
2:52 PM
これが「積」の定義で、
2:53 PM
2:54 PM
これが「和」(または「余積」)の定義です。
3:00 PM
例えば整数全体を整除関係(a が b を割り切る ⇔ a ≦ b)によって半順序集合と見なした圏では、a, b の「和」がその最小公倍数、「積」が最大公約数になります。 (edited)
Avatar
@taketo1024#1158 ありがとうございます!圏論についての知識がなさすぎてすぐには理解できなさそうですが後でちゃんと読みます💦
1:35 AM
#math でやればよかった😅
👍 1
😎 1
Avatar
#math に移動しました。
Avatar
We all love enums! Every time when I am adding Result to project, I wonder why it is not included in stdlib. enum Result { case success(T) case failure(Error) public init( value: T) { self = .success(value) } public init( error: Error) { self = .failure(error) } } This is very powerful type while using it with Swift pattern matching operators like switch or if-case .
10:22 AM
繰り返す・・・
Avatar
Kishikawa Katsumi 1/26/2018 10:24 AM
今までの何か違うのかと思ったけど、シンプルな提案だな。。。 (edited)
Avatar
Typed Throws のステータスってどうなってるんだろう?
3:17 PM
async/awaitFuture 的なものがないと並列実行ができないから、それとの絡みで Result も結局必要になる気がしてる。
Avatar
omochimetaru 1/26/2018 3:18 PM
Futureはラトナーの提案で実装例が示されてますよ
Avatar
うん、それ見て Result も必要そうだなと思った。
3:21 PM
あの Future の例だと失敗しない Future が作れない(ようになってたはず)。 (edited)
Avatar
omochimetaru 1/29/2018 3:17 AM
Future<T>とFailableFuture<T>を作るのではなくて、Future<T>とFuture<Result<T>>で表すためにってことですか? (edited)
Avatar
はい。 extension<T> Future where Value == Result<T> ができれば↓みたいに便利メソッドは生やせるので。 extension<T> Future where Value == Result<T> { func get() async throws -> T { return try await get().get() } } (↑のままだと get がオーバーロードになってしまうのが微妙ですが。)
👀 1
Avatar
今更ながら見たんですが、LLVM Developoer's MeetingでChris Lattnerが発表したSILの動画がかなり分かりやすくまとまっていて素晴らしい資料でした https://www.youtube.com/watch?v=Ntj8ab-5cvE
🙏 1
Avatar
見よう
Avatar
omochimetaru 2/1/2018 2:54 PM
LLVMの会のほうで結構Swiftのコアな情報が発表されてるの最近まで気がついてなかった、この動画は未チェックだったので見ます
Avatar
今までSwiftのドキュメント見て頑張って理解しようとしてたけど、こっちのほうが断然分かりやすいw
2:57 PM
あとMacアプリでASTとかSIL出力できるのを見つけて、手元で簡単なコードを試す分には結構便利かも https://github.com/alblue/SILInspector
SILInspector - An application for experimenting with Swift's Intermediate Language
3:01 PM
ジェネリクス, Value Witness Table, Protocol Witness Tableあたりのコード生成についてはこれが良い↑
Avatar
ほー そろそろSIL上でVtable, Witness Tableらへんの挙動を調べようと思ってたので助かります!
Avatar
norio_nomura 2/3/2018 4:44 AM
masterはconditional conformanceをランタイムチェックできるようになったぽい。 https://github.com/apple/swift/pull/14368
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...
😍 1
Avatar
もどかしいさんがSwift Compilerについて細かい説明を書くプロジェクトを見つけました。ブログ記事自体は皆見れるけど、記事中のソースコードとか重要なとこはパトロンしかアクセス権無いという面白い仕組みでした。とりあえず課金しちゃった https://www.patreon.com/modocache/posts
Become a patron of modocache today: Read 14 posts by modocache and get access to exclusive content and experiences on the world’s largest membership platform for artists and creators.
🙂 2
7:31 AM
ブログ記事はこちら https://modocache-io.herokuapp.com
Avatar
omochimetaru 2/6/2018 8:01 AM
func < を定義したときに <= とか > が使えるようになるのって Comparable なときだけか。 Optional<Cat> に < を定義する時とか、 Conditional Conformance があると楽になるね。
Avatar
Comparableのデフォルト実装ですね
Avatar
omochimetaru 2/6/2018 8:02 AM
なるほど
Avatar
omochimetaru 2/6/2018 8:03 AM
もうちょっとでCC来るからこのタイミングで <= の自前定義するの萎えるw
Avatar
haskellみたいにどれか一個定義したら残りも使えるのだとかっこいいのに
Avatar
omochimetaru 2/6/2018 8:03 AM
ハスケルのそれってどうやってんだ
8:04 AM
うまい構文が無いと循環したりしそうだ
Avatar
関数と型のセットで内部的には別の型を割り振ることでextensionを切り替える、とか出来るのでは?と思った
Avatar
ハスケルライクにできるのか試していたらillegal hardware instructionとかいう不吉なエラーで死んだ... https://gist.github.com/ukitaka/a995c8821ad5a831f675c8954ff1b713
haskell-like-func-def.swift
😨 2
Avatar
odd evenのほうは行けてるみたいですけど次の問題はどちらか片方は実装という制限が付けられないことですね
Avatar
片方は実装という制限が付けられない
これがないなら今の方がマシそうですねぇ。
Avatar
tarunon - 今日 午後5時4分 関数と型のセットで内部的には別の型を割り振ることでextensionを切り替える、とか出来るのでは? これは現在のSwiftの話ではなく、理論上はという意味でし
Avatar
OddableとEvenableに分けるしか
Avatar
ですね〜
Avatar
9.3 beta ではクラッシュは再現しませんでした。
👍 1
9:01 AM
extension のデフォルト実装間で無限再帰っぽいですね。4.1で挙動が変わったということか。
Avatar
extension MyInteger where @implemented(isOdd) { var isEven: Bool { return !isOdd } } こういう感じのがあれば出来るが…
9:02 AM
いやーこれはw
Avatar
omochimetaru 2/7/2018 2:30 AM
昨日 https://vapormeetuptokyo.connpass.com/event/77789/@noppoman の発表で、 SwiftPMで作ったdylibにたいして、 ld で(当然、マングルされている)シンボル引っ張ってきて それを dlopen でリンクして、 NodeJSからSwiftがネイティブブリッジ呼び出しできるよ っていうワイルドな話があって面白かったんですが、 実際このアプローチなら C <- Swift だけでなく Swift <- C , Swift <- C++, Swift <- Python, Swift <- Ruby みたいなブリッジが可能なので、 C/C++でやってた事がSwiftに置換できる余地があって良さそう
## イベント概要 # VaporMeetupTokyo Vapor meetup in Tokyo 1st. Youtubeで配信します!19:00 スタート https://www.youtube.com/channel/UCQSdXXHq6tvvTDA58EqcfEQ/live Swiftはバージョン3以降OSSとなり、LinuxやAndroidなどのAppleプラットフォーム以外での利用シーンも広がってきています。 サーバサイドでSwiftを使うことも選択肢の一つになってきています。 日本ではまだあまり有名になっていないサーバサイドSwiftの代表的なフルスタックMVC...
Avatar
オーディエンスの反応がイマイチだったのでつまんない話してるのかなーって心配してたんですが、面白いと言ってくれてホッとしました😭 資料上げてシェアしますね。
🙏 1
Avatar
おもちが一人で爆笑してたw
2:46 AM
あれは笑うところでしょ。
Avatar
レベル高すぎて追いつけませんでした 🙇
Avatar
資料読み直したいです!
Avatar
omochimetaru 2/7/2018 2:47 AM
そこらへんのCライブラリ互換性は、Rustがパパーっと先に進んじゃったから、Swiftのフロンティアが若干食われちゃった
Avatar
(シンボルとか普段全く触らないからな…(白目
Avatar
ネイティブバインディングからサーバーサイドSwift初めてみるのはありかと思いますねー
Avatar
omochimetaru 2/7/2018 2:52 AM
現状の道具だとRubyエンジニアにはそのブリッジするところのハードルが高すぎると思うんで、 そこの面倒見てくれるツールキットやボイラープレートジェネレータを作ったりするといいのかなとちょっと思いました。
Avatar
たしかに。ブリッジのハイレベルなインターフェースを提供できる仕組みの開発は検討してみます。
Avatar
omochimetaru 2/7/2018 2:57 AM
@noppoman ちなみに、Swift開発チームでは今、逆方向で、 Swift -> Python のブリッジの導入をすすめてます https://forums.swift.org/t/se-0195-introduce-user-defined-dynamic-member-lookup-types/8658
The review of “SE-0195 — Introduce User-defined “Dynamic Member Lookup” Types” begins now and runs through January 29, 2018. The proposal is available here: https://github.com/apple/swift-evolution/blob/master/proposals/0195-dynamic-member-lookup.md 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
サーバーレスでモバイルエンジニアが簡単にWebアプリ作れちゃうみたいなのも目標の1つではあるので、サーバーレスが提供している言語で提供すると使ってくれる人がいるかも?
Avatar
omochimetaru 2/7/2018 2:58 AM
// import pickle let pickle = Python.import("pickle") // file = open(filename) let file = Python.open(filename) // blob = file.read() let blob = file.read() // result = pickle.loads(blob) let result = pickle.loads(blob) こういうの。
2:59 AM
なるほど > サーバーレス
Avatar
この逆方向のやつ、Swiftからの他言語の実行方法が気になりますね
Avatar
omochimetaru 2/7/2018 3:13 AM
Python, Ruby, JSについては、処理系のC APIですね。
3:14 AM
こういうやつ。
Avatar
あーなるほど!
Avatar
omochimetaru 2/7/2018 3:17 AM
↑の提案は、Swiftの式に対するメソッド呼び出しにたいして動的にフックできる言語機能を追加するだけで、Pythonとかの個別言語との実際のバインディングは、そのフックのところで、C APIを呼ぶようにライブラリとして用意する感じですね
3:19 AM
なので、noppomanさんがおそらく考えてる、JSプログラマがSwiftもちょっと入れてみるっていう合流の方向とは逆で、 SwiftプログラマがPythonのライブラリ資産をつまみぐいで使える、みたいな方向ですね
Avatar
https://github.com/apple/swift-evolution/blob/master/proposals/0195-dynamic-member-lookup.md こっちみて使い方わかりました! なるほどですねー 機能としては面白いけど、そんなヘビーに使われなそうw
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
3:23 AM
言語ラップ以外にも使い方はあると思いますが
Avatar
omochimetaru 2/7/2018 3:24 AM
ああ、JSONの例とかも載ってますね。
👍 1
Avatar
#server-side  のほうに資料upしましたー
👍 1
Avatar
ちなみに、昨日話していたアトリビュートは @_cdecl です。 @_cdecl("foobar") public func foobar(_ x: Int32) -> Int32 { return x + 1 } こんな感じで書いておくと、 int32_t foobar(int32_t x); としてシンボルが出来るので、Swift の Mangling に依存する必要が無くなりますよ、と。
Avatar
ありがとうございます。 早速使ってみます
Avatar
Undocumented なので将来仕様変更の可能性は高いですが、 swift の ABI 追うよりはマシだと思います。
4:28 AM
$ swiftc -emit-objc-header -emit-library MyLibrary.swift みたいにすると、 MyLibrary.h が生成されて、 C からどう呼べるのか分かると思います。ただ、この生成されたヘッダーファイルは Linux でも Obj-C に依存する余計なものがいっぱい吐かれるので、そのままでは使えないとおもいますが。
🙏 1
Avatar
僕としては機械学習で Python が避けられない現状なので、そのコードを Swift で書けるようになるのはうれしいですね。↑は一般的な言語仕様として提案されてますが、(提案者の) Chris Lattner の今のポジションから考えてもそこがメインターゲットだと思います。
Avatar
norio_nomura 2/9/2018 6:43 AM
Conditional Conformanceってジェネリックパラメータによって実装を変える事が出来ないのね。 protocol P {} extension Optional: P where Wrapped == Int {} // error: redundant conformance of 'Optional<Wrapped>' extension Optional: P where Wrapped == String {}
Avatar
omochimetaru 2/9/2018 6:44 AM
あ〜なるほど。
Avatar
norio_nomura 2/9/2018 6:46 AM
IntStringなら一括りにするプロトコルを使えば protocol WrappedP {} extension Int: WrappedP {} extension String: WrappedP {} extension Optional: P where Wrapped: WrappedP {} とか出来るけど、タプルがラップされてる場合に使えない。
Avatar
AnyまたはIntとかもダメですよね
8:42 AM
Existentialもダメなのでは?
8:42 AM
ExistentialはCondConfにできなくね
8:43 AM
extension Optional: P where Wrapped: Animal { ... } で、Optional<Animal>はPにならないですよね
Avatar
Animalprotocol の場合ってことですね?
Avatar
そうでうs
Avatar
Optional<Cat> is P だけど Optional<Animal> is P ではないと。
Avatar
そのはず
8:51 AM
そしてOptional<Animal> is Pにする手段が存在しないのでは
8:51 AM
LTネタ膨らみすぎて5分に収まらないなぁ
Avatar
ややこしすぎるので existential 禁止にしてほしい・・・。
8:53 AM
それか Any<FooProtocol>
Avatar
それがExisitentialになる感じです?それとも自動生成のType-erasure?
Avatar
Optional<Any<Animal>>Optional<AnyAnimal> と等価なイメージなので後者ですが、これも existential なのでは? (edited)
Avatar
私はExistentialはAnimalではないが、Type-erasureならAnimalであるという理解です
Avatar
ああ、現状ではそうなんですが、
8:55 AM
↓の文脈では existential も Animal になるのかなと。 https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials
swift - The Swift Programming Language
8:56 AM
typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element> とするためには、 Any<FooProtocol> is FooProtocol じゃないとダメかと思います。
Avatar
フーム
8:58 AM
Generalized Existentialってまだ全然議論されてないですよね、これが来た時に
8:59 AM
Existentialの名を冠するのか、別の名前になるのかが気になる
Avatar
omochimetaru 2/9/2018 8:59 AM
全然議論されてない
なんか、重要なテーマは実は2, 3年前に話されてて、MLに埋もれてる事がまあまあある
Avatar
掘らなきゃいかんかー
Avatar
omochimetaru 2/9/2018 9:00 AM
フォーラムになったし検索してみたら出てくるかも。
Avatar
Hi swift-evolution, I was wondering if anything more detailed has been written about generalized existentials / type erasers. I noticed that AnyCollection only delegates a number of methods to its wrapped value, but often doesn't. For example, all the conditionally inherited items aren't being delegated (e.g. min()). This behavior was surprising to me (but makes sense once I thought about it longer). How would this work with generalized existentials? Are generalized existentials in scope...
9:01 AM
あった
Avatar
omochimetaru 2/9/2018 9:01 AM
フォーラムになってアイコンでかすぎる・・・
Avatar
www
9:02 AM
Swift4入るんか?入らんぞって感じに見えるな
9:03 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
9:03 AM
こっちか
9:03 AM
言語サポートとしてはExistential推しだから、is Animal == trueな未来は来ないんじゃなかろうか
9:10 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
9:10 AM
ここ見るといけるようになる事を考えてる気がする
Avatar
これが来た時に Existentialの名を冠するのか、別の名前になるのかが気になる
AnySequence とか個別に実装するの辛い問題はあるので、 existential と呼ぶかどうかはおいといて自動 type erasure はほしいですね。
Avatar
isがtrueじゃないとこうはならない
9:11 AM
9:11 AM
読み違えてた
9:14 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
9:15 AM
X.SelfがGenericsに渡せる状態、つまりis Xな型として振る舞えるようになっているということかな (edited)
9:16 AM
Exisitential opening って書いてあるからまさにそれっぽい
Avatar
このevolution通れば互換性のためのAny<FooProtocol> is FooProtocolを捨てて、Genericsに渡す際には明示的にopenさせる方向に進むっぽいですね〜正しい進化ではある
Avatar
typealiasを都度宣言させるのも良さそう
9:38 AM
可能ならwhereなしでもtypealiasの宣言後初めて使えるぐらいにした方が、認知はずれないと思う
Avatar
Swift CompilerをSwiftで書いたやつとか、LLVMのSwiftラッパーとかあって面白いですね https://github.com/yanagiba/swift-ast https://github.com/harlanhaskins/Kaleidoscope-Swift https://github.com/llvm-swift/LLVMSwift
swift-ast - A Swift AST parser and visitor that is written in Swift.
Kaleidoscope-Swift - A compiler for the Kaleidoscope sample project, written in Swift
LLVMSwift - A Swift wrapper for the LLVM C API (version 5.0)
Avatar
SILのテストコードがどこにあるか知っている方いますか?SwiftParseTestsとかSwiftASTTestsは見つけたけど、それのSIL相当が見つからない... (edited)
Avatar
swift/test/SIL SILGen SILOptimizer sil-func-extractor sil-llvm-gen sil-nm sil-opt sil-passpipeline-dump
12:33 PM
ここらへんじゃないですか?中は読んでないですが
Avatar
すみません、言われてみればリポジトリから探せば普通にあった。ビルド時に生成されたXcodeプロジェクトから見つからなかっただけでした.. ありがとうございます! (edited)
Avatar
omochimetaru 2/11/2018 5:57 PM
テストは基本的にtest以下とvalidation-test以下にまとまってて、テストを回す専用のスクリプト機構で流すようになってます xcodeからだとそのスクリプトを叩く発火用のターゲットしか見えないですね。 一部のユニットテストだけはxcodeでも素直に見えてる。
Avatar
よくよく見たらTestingのドキュメントにちゃんと書いてありました。テスト用のスクリプトも目を通してみます。
🙂 1
Avatar
omochimetaru 2/13/2018 1:13 AM
This is a dusted off and updated version of PR13361, which switches from DynamicMemberLookupProtocol to @dynamicmemberlookup as was requested by the final review decision. This also rebases it, up...
1:14 AM
テストのswiftソースのインデントが2だ・・・
Avatar
swiftのソースってそこら中インデント2じゃないっけ
Avatar
omochimetaru 2/13/2018 1:16 AM
マジ?気づかなかっただけか
Avatar
Xcodeで書くとデフォルトのインデントが4なのとプロジェクト単位で切り替える手段が無いらしくブチ切れ
Avatar
omochimetaru 2/13/2018 1:17 AM
それクソ不便だよねw swiftのcxxが2だからシコシコ切り替えてる
Avatar
Kishikawa Katsumi 2/13/2018 1:19 AM
Xcodeはプロジェクト単位でインデント設定できるよ
Avatar
プロジェクト単位で切り替える手段が無い
Project Navigator でプロジェクト選んで、Utilitiies で プロジェクト毎のデフォルトインデント設定できるとおもいます。
(edited)
💖 1
Avatar
お!
Avatar
Kishikawa Katsumi 2/13/2018 1:20 AM
プロジェクトファイル(青いやつ)を選択して右ペインのText Settings
Avatar
ありがとうございます。ファイル単位とXcode単位のしか見つけれてなかった
Avatar
ファイル単位でもいけたような
Avatar
omochimetaru 2/13/2018 1:34 AM
!!!!!!!!!こんなところに!!!!!
1:34 AM
ファイル単位そういうことか
1:34 AM
同じ場所にあった マジか・・・ ありがとうございます
Avatar
Kishikawa Katsumi 2/13/2018 1:35 AM
まあ普通わかるはずないUIだと思う。
1:36 AM
ファイル単位はまあJSとHTMLみたいな混合のときに使うんだろうけど、ほとんど使われないだろうし。
Avatar
僕はつい最近までプロジェクト単位知らなくて、偶にあった2スペースインデントのプロジェクトではファイル単位でシコシコ設定していました😇
Avatar
前rintaroさんが諦めてるみたいなの言ってたの覚えてて同じく諦めてた😇
Avatar
Kishikawa Katsumi 2/13/2018 1:56 AM
プロジェクト単位のはわかりにくいけど、設定してコミットしておけば基本的に違うインデントやタブが混ざったりするのを防げる。
Avatar
omochimetaru 2/15/2018 6:16 AM
I frequently find myself wishing for more expressivity when using predicate functions, and so I end up defining these operators so I don’t have to create cluttered little closures: func && ( lhs: @escaping (Element) -> Bool, rhs: @escaping (Element) -> Bool ) -> (Element) -> Bool { return { lhs($0) && rhs($0) } } func ( lhs: @escaping (Element) -> Bool, rhs: @escaping (Element) -> Bool ) -> (Element) -> Bool { return { lhs($0) rhs($0) } } prefix func ! ...
6:17 AM
Bool関数を合成するオペレータを定義してこういうの書きたいってスレ var a = 1...10 a.filter(isEven) // [2, 4, 6, 8, 10] a.filter(!isEven) // [1, 3, 5, 7, 9] a.filter(isEven && isMultipleOfThree) // [6] a.filter(isEven && !isMultipleOfThree) // [2, 4, 8, 10] a.filter(isEven || isMultipleOfThree) // [2, 3, 4, 6, 8, 9, 10] a.filter(!(isEven || isMultipleOfThree)) // [1, 5, 7]
6:17 AM
// current a.filter({ isEven($0) && isMultipleOfThree($0) }) // pitched a.filter(isEven && isMultipleOfThree)
Avatar
@ukitaka
😳 1
Avatar
omochimetaru 2/15/2018 6:18 AM
@t.ae 好きそう
Avatar
いいですけど述語をたくさん定義するのが微妙な気もしますね
6:23 AM
filter以外で便利になるケースがいまいち思いつかない気もしますし
Avatar
omochimetaru 2/15/2018 6:24 AM
removeとか。
Avatar
これが出来るなら関数合成ももっと楽にできて欲しい
6:24 AM
(S) -> T と (T) -> Uとか
Avatar
omochimetaru 2/15/2018 6:25 AM
However, the thought occurs to me, is it possible to make this more general? As in, given two functions f and g, where the return value of g matches the input to f, can we make something like f(g) or f.g resolve to the closure { f(g($0) } or equivalent?
Avatar
where系のは全部行けるか。 firstとかindexとかも行けると考えると役立つかもですね
Avatar
デスヨネ
Avatar
omochimetaru 2/15/2018 6:25 AM
Nevinさんのレスがそれかな? (edited)
Avatar
Ben_Cohen
>9h
>Oh, also +1 for also adding f • g
Avatar
thumbs upしとこ
Avatar
omochimetaru 2/15/2018 6:27 AM
guardでの早期脱出は一種のフィルタなんだけど、フィルタを抜けると同時に型変換が生じるから、こういうふうには合成できなそうだなあ
Avatar
omochimetaru 2/21/2018 3:05 AM
import UIKit class Cat {} func f1() -> ObjectIdentifier { let cat = Cat() return ObjectIdentifier(cat) } func test1() { var a = Set<ObjectIdentifier>() for _ in 0..<10000 { let id = f1() if a.contains(id) { print("conflict") } a.insert(id) } } test1()
3:06 AM
異なるオブジェクトに対して同じObjectIdentifierが生成される可能性がある実証↑
Avatar
やばそう
Avatar
omochimetaru 2/21/2018 3:06 AM
ObjectIdentifierが引数で受けたオブジェクトを内部で弱参照で保持し続けていれば
3:07 AM
弱参照はフィールドは解放するけどオブジェクトスペースは保有しつづけるので、同じヒープアドレスが使われることがなくて、この現象は起こらないんだけど
3:07 AM
そうなってなかった。
Avatar
あー
3:07 AM
class型だとそうなるか
3:08 AM
Typeの場合はそもそも確保され続けるから安全なはず(どちらかと言えばTypeに使う用途が多い)
Avatar
omochimetaru 2/21/2018 3:08 AM
Typeをキーにした辞書を作るために使うパターンなら問題ないね。
Avatar
ことこれに関しては自分でHasshable作るのが良いねとなるかなぁ
3:09 AM
Hashable.hashValueが自動生成されるのはいつからだっけ (edited)
3:09 AM
4.1でくる?
Avatar
omochimetaru 2/21/2018 3:10 AM
4.1じゃなかったっけ?もう待ちくたびれた
Avatar
4.1できてなかった
3:10 AM
Xcode9.3b2🙅
Avatar
norio_nomura 2/21/2018 5:22 AM
インスタンスのObjectIdentifierをキャッシュのキーにしててコンフリクトする不具合を踏んだ事がある。
Avatar
omochimetaru 2/21/2018 5:22 AM
おお・・・
5:23 AM
気づかないと踏みそうです、発生率も微妙な感じなので厄介
5:23 AM
知らぬ間にキャッシュのキーが衝突して上書き、だと、上書きした後古い方を読んだ時に不整合が出るので、かなり厄介なタイプのバグだ
Avatar
norio_nomura 2/21/2018 5:25 AM
Sometime ObjectIdentifier(self) might collide between tests in SourceKitCrashTests. The collision caused fail on testAssertHandlerIsNotCalledOnNormalFile. Reproduced log with printing cacheKey: Tes...
Avatar
omochimetaru 2/21/2018 5:25 AM
SwiftLint!w
5:25 AM
(あれっ、この話し前聞いた気がしてきた)
Avatar
norio_nomura 2/21/2018 5:26 AM
ありそうw
😁 1
Avatar
norio_nomura 2/21/2018 5:40 AM
発生率も微妙な感じなので厄介 これもswiftlintの実行では発生せず、テストでしか発生しませんでした。
Avatar
Kishikawa Katsumi 2/22/2018 11:16 AM
== の比較はコンパイルできるけど!=だとBinary operator '!=' cannot be applied ...と言われるプロトコルがあって、なんでかなと思ったら、==のオーバーロードだけ定義されてた。 (edited)
Avatar
ObjectIdentifier提案した悪い子僕だったのでは…w
Avatar
僕も最近そのルール知りました !=> は Equatable や Comparable に準拠してないと自動定義されない
Avatar
Kishikawa Katsumi 2/22/2018 11:20 AM
!=>って自動定義なんです?プロトコルエクステンションで ==や>を使って定義されてるんじゃないですかね。 (edited)
Avatar
自動定義というか、エクステンションで生えていて、 == や < の呼び出しになる
Avatar
Kishikawa Katsumi 2/22/2018 11:21 AM
ありがとうございます。
Avatar
Tupleに生えなくて辛いことがあったりしますね
11:23 AM
Pair<A, B>ができる
Avatar
Kishikawa Katsumi 2/22/2018 11:29 AM
@tarunon Tupleで、っていうのはどういう場合ですか?
Avatar
[(Int, Int)] 同士の == が取れないとか?
Avatar
ネストした系に困って、==をoverloadで定義しても、!=は生えない
11:30 AM
!=
11:30 AM
を使いたいならそっちもoverload
Avatar
Kishikawa Katsumi 2/22/2018 11:38 AM
== だけ定義されてたら警告でFixitで!=を作ってくれるといいな。
Avatar
そのプロトコルをEquatable準拠とするべきなのでは。
Avatar
Kishikawa Katsumi 2/22/2018 11:45 PM
まあそうだと思うんですけど、==だけ定義するっていうのはなんか理由があるんですかね。 (edited)
Avatar
Tupleはnon nominal typeなので
11:46 PM
Equatable準拠できない
Avatar
Kishikawa Katsumi 2/22/2018 11:47 PM
Tupleはそうですね。今のところ要素数の数だけ==と!=をオーバーロードするしかない。
Avatar
タプルも6要素まではstdlibで定義されてるはず。
Avatar
Kishikawa Katsumi 2/22/2018 11:52 PM
Yes.
Avatar
入れ子がキツい
Avatar
Kishikawa Katsumi 2/23/2018 6:06 AM
SwiftSyntaxでコード整形ツール作ってみました。 https://github.com/kishikawakatsumi/swiftfmt 例によって完璧には遠いんですけどまあまあ動きそうな感じ。ただもっとキレイに実装できそうなのと、将来的にはSwiftSyntaxのデータ構造のまま扱えるようにしたいのでどこかの時点で書き直すと思います。
swiftfmt - Format Swift code
🙌 2
Avatar
Kishikawa Katsumi 2/23/2018 7:21 AM
昨日==だけが定義されてたコードはSwiftSyntaxの https://github.com/apple/swift/blob/master/tools/SwiftSyntax/Syntax.swift#L157-L160 この部分です。
swift - The Swift Programming Language
Avatar
Kishikawa Katsumi 2/23/2018 7:29 AM
興味深いのは(もしかしたら変わるのかもしれないけど)乗算に使われる*@available(*, unavailable, deprecated)*はSyntaxの段階ではトークンとしては同じもの、String Interpolationの"...\(...)..."開きカッコはLeft parenthesisだけど閉じカッコはStringInterpolationAnchorっていう特別なトークンだったということ。 (edited)
Avatar
Syntax が protocol になったのが最近 https://github.com/apple/swift/pull/14122 で、 != が必要になった人が今までいなかっただけだと思います。
This patch, more in line with how I hoped we could structure the API, moves from a class-based model with Syntax as a superclass to a protocol-based model where each struct conforms to Syntax. This...
Avatar
これSyntaxがEquatableじゃないのは
8:29 AM
FooSyntaxとBarSyntaxを比較するからか
Avatar
Syntax を existential として扱いたいからだと。
Avatar
中身が===なのも面白いな
8:32 AM
ExistentialをProtocolに適合させるようなサムシングが欲しくなってくるな
8:33 AM
そうするとExistentialがProtocolのまま表記されてるのがconfuse過ぎて死ぬか。
Avatar
libswiftSwiftSyntax.dylib はXcode 9.3 betaに入ってないのね。リリース版にも入らないのかな?
Avatar
swift-4.1-DEVELOPMENT-SNAPSHOT-2018-02-22-aとかには入ってるのに。
Avatar
Kishikawa Katsumi 2/23/2018 11:03 AM
あら、9.3で確かめようと思ってHighSierraにする準備をしてたのに。
11:04 AM
File Vaultの解除に1週間くらいかかった。
Avatar
READMEに Swiftfmt requires Swift 4.1 toolchains. って書かれてるけど、swift-4.1-branchではなくmasterのスナップショットが必要ぽい?>swiftfmt
Avatar
Kishikawa Katsumi 2/23/2018 11:06 AM
swiftfmtはtrunkのスナップショットがいります。
11:06 AM
README直し忘れですね。ちょっと前に作ったものからコピーしたので。
11:06 AM
4.1snapshotとtrunkのsnapshotでだいぶ機能が違うんですよね
11:07 AM
対応してるシンタックスがダンゼン多い。
11:07 AM
最初は4.1snapshotで作ってたのでlibSyntax自体は使えると思うんですよね。Xcode 9.3
Avatar
linuxだとswift-4.1-DEVELOPMENT-SNAPSHOT-2018-02-22-aにも入ってないぽい。
Avatar
Kishikawa Katsumi 2/23/2018 11:08 AM
-emit-syntaxがあるならSwiftSyntaxはそれをデコードしてるだけ。
11:08 AM
swiftc -frontend -emit-syntax fileって失敗します? (edited)
Avatar
/Users/norio/github/swiftfmt/Sources/swiftfmt-core/AlignmentFormatter.swift:9:8: error: no such module 'SwiftSyntax' import SwiftSyntax ^
11:09 AM
swiftc -frontend -emit-syntax は動きます。
Avatar
Kishikawa Katsumi 2/23/2018 11:10 AM
なるほど。libSwiftSyntaxがないのかな。
Avatar
無いです。
Avatar
Kishikawa Katsumi 2/23/2018 11:10 AM
そうなんですね。
11:11 AM
実は4.1スナップショットだとちょっと辛かったので-emit-syntaxを自分でデータ構造に変換したバージョンとかあるのでそれならもう少し幅広く使えますね。 (edited)
Avatar
norio_nomura 2/24/2018 6:24 AM
Swift 4.1には標準でswift formatってのが含まれてるぽい。 $ TOOLCHAINS=org.swift.4120180222a swift format --help 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
Kishikawa Katsumi 2/24/2018 7:15 AM
これ4.1からだったのか。もっと前からあるもんだと思ってました。
Avatar
norio_nomura 2/24/2018 8:22 AM
あいや、Xcode 9.3には含まれてないぽい。
Avatar
norio_nomura 2/24/2018 8:30 AM
swift-formatの仕組み自体はもっと前からあったけど、シンボリックリンクがちゃんと作られる様になったのが4.1からぽい?
Avatar
SILに詳しい人に質問です。 この記事の Eq.sil ケースをコンパイラへの最適化フラグ (-O) ありなしで結果が変わるのは、!= オペレータの関数を実行するために一時的に使用する値にわざわざalloc_stack使う必要ないという最適化が効いているからですか? https://qiita.com/Kuniwak/items/cbf6b88db249838895b5#補足-最適化をしない場合の比較 (edited)
Swift におけるパフォーマンス比較を、nil 判定を例に解説します。なお、パフォーマンスを比較する上で、コンパイル時の最適化[^1]の様子を観察することはとても重要です。この記事では、最適化の様子を中間生成物を通して観察する方法に...
Avatar
予想ですけど、 インライン最適化とSSA依存解析で、右辺値の構築が削除されるのではないでしょうか
10:13 AM
「ある計算の答えを出すために必要な事前の計算は何か?」というのがグラフ構造にできるんですけど、 それをやる前処理として変数を削除して定数だけにした形式のSSA があって、SILはSSAなのでそうした最適化も入っているはずで
10:14 AM
!= の実行の部分をインライン展開すると、最終的に、比較してる右辺を組み立てる部分グラフが完全に要らないってことが
10:14 AM
解析できるはず・・・
10:16 AM
正確な答えを知るためにはコンパイラの中の最適化を有効化する部分をちょっとずつ減らして (LLVMライブラリが最適化の機能ごとにセットアップできる設計になっているから) どれを入れてくと最終的に同じ状態まで最適化される、というのを調べないといけなそう
Avatar
これがSSA依存解析なのか。SSAは未使用の変数を探すぐらいに使うものだったと思ってたけど、コントロールフロー内の部分グラフにも適用できるんですね。完全に勘違いしてました...
Avatar
細かいところで、依存解析をすると、計算の順序を入れ替えられる場所が見つかったりします。 (たとえば a + 1 == b + 1 の両辺はどっちから構築しても同じ結果になる) それで、メモリ上の変数の値は一度レジスタに置かないと計算ができないんで、 命令の順番を入れ替えてなるべくレジスタに同じ値を長くおいておければ、 メモリへの退避書き込みと読み出しの回数を減らせて早くなるとか、そういう話を聞いたことがあります (edited)
10:24 AM
あ、でもこれはCPUに依存した話だからLLVM-IR以降のアセンブラ生成時の最適化だからSILは関係ないですね
Avatar
それって定数伝播・畳み込みというやつですか?
Avatar
↑のwikiのページだと 「レジスタ割り付け」ですね
Avatar
これがレジスタ割り付けか
Avatar
定数伝搬と畳込みは、定数式をコンパイル時に事前に計算しちゃって、その計算結果をちょくせつコードに埋めておく
10:30 AM
あ、でも、そうか、右辺側のnilは定数ですね。
Avatar
なるほど、だからレジスタ割り付けはSILの最適化の説明には出てこないのか。今このへんのコンパイラ最適化の手法について勉強中でまだはっきりと違いが分かってなかったので、雰囲気だけ分かりました
Avatar
僕も雰囲気しかわかってないです
Avatar
コンパイラの本読んで出直して来ます。まだまだSILOptimizerのGeneric specializationに辿り着くまで先は長い... Guaranteed optimizationsだけでも難しい
Avatar
最適化は一つ一つが個別のトピックだから大変そう・・・ Guaranteed optimizationsってなんですか?
Avatar
-emit-silgen から -emit-sil の間です。 https://github.com/apple/swift/tree/master/lib/SILOptimizer/Mandatory
swift - The Swift Programming Language
10:47 AM
-emit-silgen から -emit-sil の間です。
んー、ちょっと違うか。とにかく -Onone でも実行されることが保証されている SILOptimizer のパス群 。
(edited)
Avatar
ああ、なるほど、絶対やるって意味でGuaranteedか
Avatar
このドキュメントで見ました! Rintaro大先生がおっしゃってるように -Ononeでも走る最適化です
10:49 AM
そうそう
10:51 AM
こっちは逆に -Ononeの時は実行されないはず https://github.com/apple/swift/blob/master/docs/SIL.rst#general-optimization-passes
swift - The Swift Programming Language
👀 1
10:51 AM
いやものによるのかな
Avatar
最適化の過程dumpしてみました、上のalloc_stackが消えてる件はMem2RegってPassっぽいですね〜 https://gist.github.com/ukitaka/b7f554b1ba99a93c0808a2a2effc7b48#file-eq-sil-swift-L1060-L1183
Eq.sil
Avatar
このPass探してたところです!ありがとうございます。
Avatar
もしかしてこれが-Oの時に走るMemory Promotionのことなのか
Avatar
おおおパスごとにダンプできるのか〜
Avatar
"This pass promotes AllocStack instructions into virtual register references." なるほど、そうっぽいですね
Avatar
このPassは面白いなー。最適化って感じする
Avatar
omochimetaru 2/27/2018 5:47 AM
iOS開発とかのメモ
5:47 AM
@ukitaka さんの進捗がすごい進んでた
Avatar
最近ちょいちょいやってますね 😀
Avatar
omochimetaru 2/27/2018 5:48 AM
最適化の個別のパスごとに実行できる仕組みが整っているんですね、たしかにユニットテスト作るためにこういう機構が用意されてるはずなんですねえ https://blog.waft.me/2018/02/02/swift-sil-4/ (edited)
特定の最適化Passのみを有効にする術を見つけたのでメモ。
Avatar
ですね〜だいたいこれを使ってテストケース走らせてみてどんなことやってるか雰囲気掴みつつ勉強してます
Avatar
swiftc -emit-silswift -frontend -emit-silで出力違うの知りませんでした...
Avatar
omochimetaru 3/1/2018 4:55 AM
protocol Animal { func speak() } func callSpeak<T: Animal>(_ t: T) { t.speak() } class Cat : Animal { func speak() { print("nya") } } let cat = Cat() callSpeak(cat)
4:56 AM
-Osize でスペシャライズ版が生成されるかどうかを調べるために、そもそも -O でスペシャライズすることを期待したが、うまくいかなかった・・・
4:56 AM
CC: @kitasuke
Avatar
メモ: struct にしたら出来た
Avatar
omochimetaru 3/1/2018 5:07 AM
protocol Animal { func speak() } func callSpeak<T: Animal>(_ t: T) { t.speak() t.speak() t.speak() t.speak() t.speak() t.speak() t.speak() t.speak() t.speak() t.speak() t.speak() t.speak() } struct Cat : Animal { func speak() { print("nya") } } let cat = Cat() callSpeak(cat)
5:08 AM
t.speakが1回だとスペシャライズされない
Avatar
omochimetaru 3/1/2018 5:31 AM
structだとされる、final classだとされる、classだとされない
5:31 AM
あ、で、 -Osize にしても callSepak T == Cat のspecializeは発生した。
5:32 AM
一方、specialized callSpeak where T: Animal とか一部が削除された。
Avatar
型パラ持ってる型も同じ雰囲気で実装増やせば最適化されるのかな?
Avatar
omochimetaru 3/1/2018 8:05 AM
今やってみたけどできなかった
8:07 AM
a
8:09 AM
// specialized SpeakInvoker.invokeSpeak() sil shared @_T01a12SpeakInvokerC06invokeA0yyFAA3CatV_Tg5 : $@convention(method) (@guaranteed SpeakInvoker<Cat>) -> () {
8:09 AM
でてきた
Avatar
それできてなかったら前にgybで生成したスペシャライズ用の大量のメソッドが全くの無駄になる所だったので危なかった。
Avatar
やっぱそうかーーー
8:12 AM
それができればな
Avatar
omochimetaru 3/1/2018 8:15 AM
@t.ae のやったやつって @_specialize(where T == Int) ではだめなんだっけ
Avatar
できるか試してないんですよねそれ
8:15 AM
モジュール跨いでどうなるかが分からなかったり
Avatar
omochimetaru 3/1/2018 8:16 AM
なるほど
Avatar
あとinlinable来るなら待とうかなと
Avatar
omochimetaru 3/1/2018 8:17 AM
inlineableはインライン化だから特殊化とかまた違う気が
Avatar
あれ?何か混ざってますね……
Avatar
omochimetaru 3/1/2018 8:18 AM
特殊化の標準仕様化の提案はまだ無いはず
Avatar
インライン化は関数呼び出しのオーバーヘッドが無くなるやつ
Avatar
インライン化の過程でジェネリクスはどうなるんでしたっけ? 多分その辺で混同しちゃったんだと思うんですが
Avatar
スペシャライズはGenericsパラメータのメソッド呼び出しのテーブル参照がなくなる方
8:31 AM
witnesstableの参照はインライン化しても残ってる、気がする
Avatar
omochimetaru 3/1/2018 8:31 AM
そうだね
8:31 AM
// specialized SpeakInvoker.invokeSpeak() sil shared @_T01a12SpeakInvokerC06invokeA0yyFAA3CatV_Tg5 : $@convention(method) (@guaranteed SpeakInvoker<Cat>) -> () {
8:32 AM
↑の方見ればわかるけど、SpeakInvoker<T>のTがCatであることが確定した状態のメソッド実装が生成されてるから、TへのアクセスでCat前提のロジックになるからディスパッチが一個減る
8:33 AM
ただCat is Animal(protocol) のwitness呼び出しのディスパッチはその中で発生する
Avatar
それなー
8:33 AM
そこがなんとかなればもう一段加速出来るんやが
8:33 AM
今はまだ
Avatar
後段のcallSpeakもスペシャライズされたのができるとかじゃなかったですっけ 何か根本的に認識が誤ってる気がしてきました (edited)
Avatar
omochimetaru 3/1/2018 8:35 AM
t.ae のシナリオは型パラメータに protocol制約がかかってないんじゃない?
Avatar
ああ、いまcallSpeakは別の話でしたね
Avatar
omochimetaru 3/1/2018 8:36 AM
%3 = open_existential_addr immutable_access %2 : $*Animal to $*@opened("5DF3A8B4-1D27-11E8-8379-DCA9048BCDF8") Animal // users: %5, %5, %4 %4 = witness_method $@opened("5DF3A8B4-1D27-11E8-8379-DCA9048BCDF8") Animal, #Animal.speak!1 : <Self where Self : Animal> (Self) -> () -> (), %3 : $*@opened("5DF3A8B4-1D27-11E8-8379-DCA9048BCDF8") Animal : $@convention(witness_method) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> () // type-defs: %3; user: %5 %5 = apply %4<@opened("5DF3A8B4-1D27-11E8-8379-DCA9048BCDF8") Animal>(%3) : $@convention(witness_method) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> () // type-defs: %3
8:37 AM
これってCatがstructなんだから呼び出し削除できそうだけど・・・
Avatar
できてほしいよね〜〜〜
8:38 AM
わかるわ〜〜〜
Avatar
omochimetaru 3/1/2018 8:38 AM
コントリビューションチャンス
Avatar
一ヶ月ぐらいここでハマってたから死ぬほどわかる
Avatar
omochimetaru 3/1/2018 8:44 AM
ast
8:44 AM
改行が消えちゃった
Avatar
破壊した
Avatar
omochimetaru 3/2/2018 1:50 AM
@omochimetaru まだちゃんと追ってないんですけど、witness_methodのdevirtualize自体はあるはずなんでこのケースは最適化されてもおかしくないんですよね〜class_methodの場合はupcast命令辿っていってインスタンスがわかれば直接呼び出しになりますし、同じようにできるような気はする https://t.co/ANCH4PKgll
Avatar
なに
Avatar
omochimetaru 3/2/2018 1:50 AM
昨日の17:35のやつ
Avatar
omochimetaru 3/2/2018 1:50 AM
https://blog.waft.me/2018/01/31/swift-sil-3/ ←この記事で vtableのdevirtualizeの解説がされてるから
最近は別のことをやっていてあまりSwiftに触ってなかったのだけど、気分転換に最適化を1つ読んでみる。
1:51 AM
これを参考にwitness tableのdevirtuaizeの実装を読んだり、ユニットテストを見たりすれば
Avatar
関数は出来るけど型はまだ難しそうっていうのが
Avatar
omochimetaru 3/2/2018 1:51 AM
なんかいけるきがする
Avatar
だから関数の実装を型の方に持ってくると
1:51 AM
コントリビュートチャンスなわけだ
Avatar
omochimetaru 3/2/2018 1:51 AM
さっきのケースなら型については T= Catはもう解決してるから
1:52 AM
Cat is Animal Protocol のスコープローカルな upcast なので、↑の記事で書かれてるupcast stripping で同じようにできそうなんよな (edited)
Avatar
それさ
1:53 AM
単一の関数内で出来るのは理解できるんだが
1:53 AM
ある型に含まれるプロパティについて
1:53 AM
同じようにできるという直感が生まれないんだ
1:53 AM
なんか引っかかりが有る
Avatar
omochimetaru 3/2/2018 1:54 AM
すでにinvokeSpeakはT=Catについてspecializeされてるから
1:54 AM
更にその中で単一の関数としてやるだけじゃ?
Avatar
それは関数の話だよね?
Avatar
omochimetaru 3/2/2018 1:54 AM
うん
Avatar
Invoker<A: Animal> みたいな型があって
1:54 AM
そのプロパティが let animal: A で、その中の関数でanimal is Catをスペシャライズ出来るのか?っていうのが
1:54 AM
まだわかってない
Avatar
omochimetaru 3/2/2018 1:55 AM
あ〜
1:55 AM
animalはあくまでself.animalなのが違うってことか
Avatar
そう
1:55 AM
その最適化は、関数レベルじゃなくて
Avatar
omochimetaru 3/2/2018 1:55 AM
たしかに、再代入されてたり、オーバライドで返る値が変わる可能性があるな?
Avatar
型のレベルでメモリサイズも含めて最適化しないといけない気がしていて
1:55 AM
ちょっと難しいですね感
Avatar
omochimetaru 3/2/2018 1:56 AM
いや、ないか、struct Cat だから
1:56 AM
でもたしかに最適化パスが適用されないのはそこの違いがありそう
1:56 AM
で、一般のgetterの場合はオーバーライドがあるから駄目だわ
1:57 AM
もしかしたらそこが未実装なんじゃない?今回のケースはそれでもstruct Catだから他の可能性はないはず
Avatar
omochimetaru 3/2/2018 2:36 AM
口頭で話したまとめ self.animal は T としてBox(: Animal)された型で保存されてるはずだから、たとえ T == Cat に specialize されたメソッドの中であっても、self.animal を読む時は Cat 型としては取り出せない 実際SILを見ても取り出されてる型は Animal existential で、そこからopenするから Cat は介入してない (edited)
2:36 AM
これを解決するためには Box<Cat> が生成されてないといけない
Avatar
omochimetaru 3/2/2018 3:30 AM
@rintaro +0 系のコミットってこれが最初ですかね? タグがブレててよくわからない・・・ https://github.com/apple/swift/commit/503db5fc653c92c350d302ac8a771ee9d38bf65e
…of DefaultConventions to guaranteed. This is implemented by introducing an enum called NormalParameterConvention, enum class NormalParameterConvention { Owned, Guaranteed }; When one construc...
3:35 AM
This PR contains support for enabling via the frontend option enable-guaranteed-normal-arguments for normal parameters to be emitted at +0 instead of +1. rdar://34222540
3:36 AM
このPRからっぽいかな・・・
Avatar
omochimetaru 3/2/2018 6:28 AM
タグはブレてるけど rdar://34222540 でも追跡できそう
Avatar
class My { func get() -> Int?? { return 1 } } class MyMy: My { override func get() -> Int? { return 2 } } MyMy().get() おもちと議論しててOptionalのアレを見つけてしまった cc @koher @rintaro
Avatar
これはひどい・・・
😫 3
Avatar
omochimetaru 3/2/2018 3:56 PM
改めてみたら説明が足りなすぎる ↑のコードはオーバライドできない、ってコンパイルエラーになる。 でも、もし親が Int で 子が Int? ならオーバライドできるので、 法則が乱れてるね、という話です (edited)
Avatar
omochimetaru 3/3/2018 6:31 AM
@rintaro もう帰りましたか?
Avatar
いますよ。畳エリア。
Avatar
omochimetaru 3/5/2018 3:33 AM
protocol AppViewController { var disposeBag : DisposeBag { get } } extension AppViewController where Self : UIViewController { } // OK extension UIViewController where Self : AppViewController {} // NG こういうもんだっけ。難しい。
Avatar
あるある
Avatar
ヒラリ術を使うと protocol AppViewController where Self: UIViewController { var disposeBag: DisposeBag { get } } って宣言できる
9:40 AM
いつから出来るようになったか知らない
Avatar
omochimetaru 3/5/2018 9:41 AM
あ、そうやるのか、thx
Avatar
↑それでもextension内で例えばself.viewをいじろうとしたらselfはletだから書き換えられないよ〜〜〜みたいなことを言われたのでprotocol ~~~ class where: UIViewController にしたよ
9:41 AM
class無くてもself.view書き換えられてほしいけど
Avatar
VCの.view書き換えはちょっと野蛮じゃないか?
Avatar
あいや
9:42 AM
addSubviewも怒られた気がする
Avatar
マジ?
9:42 AM
それはいけた気がする
Avatar
mutating扱いなのかな?とか思ったけど勘違いかも。
Avatar
フーム
Avatar
viewじゃなかったかも。titleとかだったかも。
Avatar
それはありそう
Avatar
とにかくselfはletのconstantだから書き換えられませんって言われてclassを足したのは確かだと思う
Avatar
omochimetaru 3/5/2018 9:43 AM
AppViewControllerのextension funcでself.view = nil かいてもコンパイルできた
Avatar
野蛮だ
Avatar
class ナシでも?
9:46 AM
あれー
Avatar
omochimetaru 3/5/2018 9:46 AM
うん
Avatar
かしこい
Avatar
omochimetaru 3/5/2018 9:46 AM
where付ける前の事なんじゃない?
Avatar
じゃーなんか勘違いしてたかなあ
9:46 AM
うーん。そうかも。
9:46 AM
わすれてくれ
Avatar
omochimetaru 3/5/2018 9:46 AM
わすれた
Avatar
チャンミス
Avatar
norio_nomura 3/6/2018 2:08 AM
Xcode 9.3 beta 4で-Ouncheckedが無くなって-remove-runtime-assertsってのが出来た?
Avatar
omochimetaru 3/6/2018 2:08 AM
ほほう
Avatar
norio_nomura 3/6/2018 2:09 AM
SWIFT_DISABLE_SAFETY_CHECKS=YES-remove-runtime-assertsがつく (edited)
Avatar
↓の UnsafeMutablePointerUnsafePointer 型の引数に渡せるのってなんでなんでしたっけ? var a = 42 let p = UnsafeMutablePointer(&a) func foo(_ p: UnsafePointer<Int>) { print(p.pointee) } foo(p)
2:58 PM
↓これはできないのに。 let p2: UnsafePointer<Int> = p
Avatar
omochimetaru 3/6/2018 2:58 PM
暗黙のアップキャスト
2:59 PM
関数呼び出しの引数部分に関して
2:59 PM
UnsafePointer族にはいろんな変換がある
Avatar
UnsafePointer 系に特有の言語仕様?
Avatar
omochimetaru 3/6/2018 2:59 PM
一般のアップキャストじゃなくて引数評価時だけの特別なやつ
3:00 PM
はい StringはUnsafePointer<CChar>になったりしますよ
Avatar
なるほど。ありがとう🙂
Avatar
norio_nomura 3/8/2018 12:09 AM
https://talk.objc.io/episodes/S01E90-concurrent-map に出てきたconcurrentMap extension Array { func concurrentMap<B>(_ transform: @escaping (Element) -> B) -> [B] { var result = Array<B?>(repeating: nil, count: count) let q = DispatchQueue(label: "sync queue") DispatchQueue.concurrentPerform(iterations: count) { idx in let element = self[idx] let transformed = transform(element) q.sync { result[idx] = transformed } } return result.map { $0! } } } これq.sync {}を使う必要なかったりしないのかな? 間違った実装を引用していたのを修正 (edited)
We implement a concurrent version of the map method for arrays.
Avatar
transformを外でして、result[idx]に詰めるとこだけsyncの中でよさそうな気はします
Avatar
norio_nomura 3/8/2018 1:13 AM
ああ、間違った実装のものを引用してました。
1:14 AM
修正しました。
1:16 AM
で、やっぱりq.sync{}は必要なかったりしないのかな。 subscriptセットはmutableだから実装がどうなっていようとも排他処理するべきなのかな。
Avatar
omochimetaru 3/8/2018 1:35 AM
Arrayのsubscriptアクセスは排他処理しないといけないです
1:35 AM
OwnershipManifestoに、ハマりポイントとして引用されてますw
Avatar
norio_nomura 3/8/2018 1:51 AM
OwnershipManifesto通りだと、subscript getも排他処理しないといけないような。
The most important consequence of this is that two different array elements cannot be simultaneously accessed.
Avatar
omochimetaru 3/8/2018 1:53 AM
はい、そう思います
Avatar
norio_nomura 3/8/2018 2:54 AM
Arrayの代わりにUnsafeMutableBufferPointerとか使えば排他制御不要? extension Array { func concurrentMap<B>(_ transform: (Element) -> B) -> [B] { var result = ContiguousArray<B?>(repeating: nil, count: count) return result.withUnsafeMutableBufferPointer { buffer in DispatchQueue.concurrentPerform(iterations: buffer.count) { idx in buffer[idx] = transform(self[idx]) } return buffer.map { $0! } } } } ContiguousArrayに変更 (edited)
Avatar
omochimetaru 3/8/2018 2:55 AM
そうですね
Avatar
norio_nomura 3/8/2018 3:36 AM
そうか、Arrayの場合 q.sync {} が無いと cow が起きてしまうのか。
Avatar
omochimetaru 3/8/2018 3:37 AM
はい、中でいろいろとロジックが。
Avatar
norio_nomura 3/8/2018 3:40 AM
struct S { class C { init() {} } var c = C() } var s = S() DispatchQueue.concurrentPerform(iterations: 100) { idx in print(s) // `s`を使うとnot uniqueになる。 if !isKnownUniquelyReferenced(&s.c) { print("not unique") } } (edited)
Avatar
norio_nomura 3/8/2018 3:50 AM
syncなしはこうなった。 extension Array { func concurrentMap<B>(_ transform: (Element) -> B) -> [B] { var result = ContiguousArray<B?>(repeating: nil, count: count) return result.withUnsafeMutableBufferPointer { buffer in DispatchQueue.concurrentPerform(iterations: buffer.count) { idx in buffer[idx] = transform(self[idx]) } return buffer.map { $0! } } } }
Avatar
omochimetaru 3/9/2018 3:02 AM
The standard library and the compiler is now fully buildable on Windows against just the Windows SDK. In order to ensure that we flush out all the issues and ensure that we don’t regress in the future, the next large goal is to get the full test suite working on Windows as well. I have part of the tests working already. The last run with a number of my changes has us at around 80%, though I would like to decrease the number of unsupported tests (but that requires investigation into why they a...
3:03 AM
swift標準ライブラリがwindowsでビルドできるようになったそうな
3:07 AM
この辺の作業ず〜っとこのコンプナードさんとトーマスさんがやってたんだけど
3:07 AM
C++コンパイル通すところまでは良いとして
3:08 AM
Windowsのlibファイルとかdllファイルにどうやってバイナリを入れていくか、みたいな議論があって
3:08 AM
なるほど全くわからんという感じだった
Avatar
先週ここで話してた@inlineableとスペシャライズの話ですけど、改めてプロポーザル読んでみたらそもそもタイトルからスペシャライズって書いてあった。 https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
3:22 AM
The name @inlinable is somewhat of a misnomer, because nothing about it actually forces the compiler to inline the declaration; it might simply generate a concrete specialization of it, or look at the body as part of an interprocedural analysis, or completely ignore the body. However, nothing seemed to read as well as @inlinable.
Avatar
omochimetaru 3/9/2018 3:23 AM
specializeももちろん関連するけど
3:24 AM
inlineableはモジュール呼び出し側がインライン化できるように、ソースコード(AST?)をライブラリに(見えないバイナリとして)埋め込んで、
3:24 AM
呼び出し側が呼び出しコードを自分のモジュール内に生成するという話で
3:24 AM
もちろんコードが外から見えるようになるのでスペシャライズにも使えるんだけど (edited)
3:25 AM
specialize修飾子のほうは、モジュール跨ぎとかじゃなくて、 そのモジュール内でコンパイルする時に、ジェネリックパラメータを具象化したバージョンを生成するって
3:25 AM
いう、コンパイラ命令な気がする。
3:26 AM
それとも、specializeは不要になって、inlieableでのAST公開と、ユーザサイドでの特殊化した版の生成だけに
3:26 AM
一本化するというアプローチもあるのかな・・・?
3:26 AM
(C++はそういう言語やね)
Avatar
先週の文脈だと、僕のコードが手書き特殊化オーバーロードをたくさん用意してるって話だったのでそれをそのまま再現するなら@_specializeで書くのが正しいですね。
Avatar
omochimetaru 3/9/2018 3:29 AM
うん、あーあと、ジェネリッククラスの特殊化は、また別な気がする。
Avatar
including full and partial specialization of generic functions
クラスは対象外かも?
Avatar
omochimetaru 3/9/2018 3:29 AM
今ってそれはコンパイラもやってない気がするんだよね。
3:30 AM
taeの手動生成は型をまるごと書き出してるから、クラスが別に生成されて、stored propertyの型も T じゃなくて具体型なので
3:30 AM
そこが一番パフォーマンスに効いてるはず
Avatar
そうですね。そこが効かないなら中途半端になってしまいそう
Avatar
omochimetaru 3/9/2018 3:31 AM
ジェネリックなTに入れるところでboxingされちゃうオーバーヘッドがどうやら大きいよ。 (edited)
3:32 AM
そういえばコンパイラ生成のExistentialは24バイトで小さい値型ならスタック化できてるけど、TはAny等価なアプローチな気がするな
3:33 AM
落ち着いたらIRGenを見てみたい。
Avatar
この前SPMにだしたPR、LGTMされたけど、この人はコミッターではないw? https://github.com/apple/swift-package-manager/pull/1517 @ikesyo
Motivation I'd like to test generated Xcode Project on XcodeprojTests. Currently, Xcodeproj.generate returns only its path. So we can't investigate contents of the project. Description I refactored...
Avatar
omochimetaru 3/9/2018 5:04 AM
swift-package-manager - The Package Manager for the Swift Programming Language
5:04 AM
コミット無いね
5:05 AM
コミット権無くてもReviewsの欄に入れたのか。
Avatar
なるほど・・・・・・
Avatar
omochimetaru 3/9/2018 6:07 AM
spmはあまり活発じゃないのかな・・・?
6:43 AM
勝手にApprove出来る気がする
6:55 AM
6:55 AM
^ ちょっとパワーアップして、libSyntaxの出力と元のソースコードの対応がわかる機能をつけた。
6:56 AM
libSyntaxで何か作ろうという時に結構便利になった気がする。
Avatar
早くenum実装しろよ。っていう圧力かと思いました😅
Avatar
Kishikawa Katsumi 3/9/2018 6:57 AM
これは単純にサンプルが悪いです。。。
Avatar
けど素晴らしい!
Avatar
Kishikawa Katsumi 3/9/2018 6:59 AM
空白やコメントがlibSyntaxの出力に残っていて、かつこんな風にトークンの前後にくっついている、という部分を撮ろうと思って、あまりSyntaxのノード名は気にしてなかったです 😃 (edited)
Avatar
omochimetaru 3/9/2018 6:59 AM
たしかに。API使う時に、どういうのが来るのか試して確認するのめんどいから便利そう。
Avatar
Kishikawa Katsumi 3/9/2018 7:00 AM
いや、これはねえ正直に言ってめっちゃ便利ですよ。
😍 1
7:02 AM
しかしWebのUIを作るのは難しいですね。UI作るのSwift側の10倍くらい時間かかった。PR歓迎なので得意な人手伝ってほしいです。
Avatar
@omochimetaru >> Arrayの代わりにUnsafeMutableBufferPointerとか使えば排他制御不要?
そうですね
これって何がソースですか?
8:08 AM
Subscripts Much of this discussion also applies to subscripts, though in the language today subscripts are never technically stored. Accessing a component of a value type through a subscript is treated as accessing the entire value, and so is considered to overlap any other access to the value. The most important consequence of this is that two different array elements cannot be simultaneously accessed. This will interfere with certain common idioms for working with arrays, although some cases (like concurrently modifying different slices of an array) are already quite problematic in Swift. We believe that we can mitigate the majority of the impact here with targeted improvements to the collection APIs.
8:09 AM
↑このセクション自体にはUnsafePointerを使えば良いとは書いてないですが
8:11 AM
大丈夫だとわかっているから排他則とか無視したい場合には究極的にはUnsafePointerを使えばいいよ ただしなるべく保護の元でいろいろできるようにしていきたいね みたいな話が書いてあります
8:11 AM
一般的な話として。
8:12 AM
あーあとは、 Rust のsubscriptなら要素がメモリごとにわけて配置されて相互に干渉しないけどSwiftのArrayはcomputed propertyでしかないのでそういう保証はやりようがない、 みたいな話が合わせて書いてあるので
8:13 AM
逆説的に、メモリごとへの直接的なアクセスがコントロールできるならそういう事もできる、と理解しました。(これによらずとも、C/C++で一般的な事)
8:14 AM
あ、もちろん、UnsafePointerの同一アドレスへのアクセスは排他が必要ですよ。
8:16 AM
ウーンそういう意味ではどこに書いてあるというよりCプログラミング的な基礎知識という感じもしてきました。
Avatar
norio_nomura 3/9/2018 10:49 AM
SwiftLintに入れました>UnsafeMutableBufferPointer使った実装。 https://github.com/realm/SwiftLint/pull/2090
DispatchQueue.sync was required to avoid CoW on calling subscript from multiple copied instances of Array. Since UnsafeMutableBufferPointer does not cause CoW on same situation, DispatchQueue.sync ...
Avatar
norio_nomura 3/9/2018 12:11 PM
この場合、排他制御が無いとどうなるかを知る方が早いかな。
12:12 PM
import Foundation let count = 10000 var array1 = [Int?](repeating: nil, count: count) DispatchQueue.concurrentPerform(iterations: count) { idx in array1[idx] = idx } print(array1.flatMap({ $0 }).count == count) // false var array2 = [Int?](repeating: nil, count: count) let queue = DispatchQueue.init(label: "test") DispatchQueue.concurrentPerform(iterations: count) { idx in queue.sync { array2[idx] = idx } } print(array2.flatMap({ $0 }).count == count) // true
Avatar
なるほど、queueで縛らないと詰め漏れが出てきちゃうんですね [Optional(0), Optional(1), Optional(2), Optional(3), Optional(4), nil, Optional(6), Optional(7), nil ...] (edited)
Avatar
omochimetaru 3/9/2018 1:23 PM
なんでそうなるんだろうなあ
1:25 PM
内部でストレージオブジェクトの参照カウントが2になって、コピーが起きて、 コピー前のストレージに書きこむスレッドの作用が捨てられる?
1:26 PM
もしそのようなコピーが起きてるならその意味でもめちゃ効率悪い
Avatar
ああ、排他制御不要ってスレッドセーフって意味かと捉えてたけど、マルチスレッドの話じゃなくてオーナーシップの話で、しかも「不要」というのはセーフの意味じゃなくてアンセーフを前提としてるってことか。
Avatar
norio_nomura 3/9/2018 2:12 PM
内部でストレージオブジェクトの参照カウントが2になって、コピーが起きて、 コピー前のストレージに書きこむスレッドの作用が捨てられる?
そう。
Avatar
norio_nomura 3/9/2018 2:23 PM
正確には、コピー後のストレージに書き込まれてコピー後のストレージごと捨てられる。ですね。
Avatar
omochimetaru 3/9/2018 2:23 PM
あ、前と後だとそうですね、元と先が言いたかった。
Avatar
norio_nomura 3/9/2018 2:43 PM
この結果を見ると、isKnownUniquelyReferenced()って排他制御が無いとあてにならない? import Foundation struct S { class C { var name: String init(name: String) { self.name = name print("init: \(name)") } deinit { print("deinit: \(name)") } } var c: C init(name: String) { c = C(name: name) } var name: String { get { return c.name } set { if isKnownUniquelyReferenced(&c) { print("unique: \(c.name) -> \(newValue)") c.name = newValue } else { print("not unique: \(c.name) -> \(newValue)") c = C(name: newValue) } } } } var s = S(name: "初期値") let queue = DispatchQueue(label: "keep unique") DispatchQueue.concurrentPerform(iterations: 10) { idx in // queue.sync { s.name = "\(idx)" // } } print(s.name) init: 初期値 unique: 初期値 -> 0 unique: 初期値 -> 1 unique: 初期値 -> 2 unique: 初期値 -> 3 unique: 1 -> 4 unique: 1 -> 5 not unique: 5 -> 6 init: 6 deinit: 5 unique: 6 -> 7 not unique: 6 -> 8 init: 8 not unique: 7 -> 9 init: 9 deinit: 7 deinit: 8 9 (edited)
Avatar
omochimetaru 3/9/2018 2:49 PM
おーバグりまくる
3:02 PM
1. An operation taking the address of a variable is allowed to replace the reference held by that variable. The fact that is_unique will not actually replace it is opaque to the optimizer. 2. If the refcount is 1 when the reference is replaced, the referent is deallocated. 3. A different source-level variable pointing at the same referent must not be changed/invalidated by such a call. 4. If such a variable exists, the compiler must guarantee the refcount is > 1 going into the call.
Avatar
omochimetaru 3/11/2018 3:47 PM
Implement basic IRGen support for coroutines and enough optimizer support to actually generate optimized and unoptimized code from the SIL test cases in this patch. Optimization seems to break it s...
3:48 PM
コルーチンの下回り進んでた
Avatar
コルーチンって正式な Proposal になってないけど、表面的なシンタックスは別として何かしら導入する方向なのは既定路線ってことなのかな?
Avatar
omochimetaru 3/11/2018 4:05 PM
そう見えますね
Avatar
それは楽しみだ。 Swift 5 は無理かなぁ?
Avatar
omochimetaru 3/11/2018 4:07 PM
5はしばらく来なくて4.Xを引っ張る気がする
Avatar
年 1 回メジャーリリースする方針なわけではないのか。
Avatar
omochimetaru 3/11/2018 4:09 PM
リリースサイクル的な話はなかった気がするなあ
Avatar
最近、 inout 的に @escaping なクロージャ式の中からアクセスできないようにするけど、特に out したいわけじゃないというのを表せるものがあればいいんじゃないかという気がしてるですがどうでしょう↓の asyncAfter のクロージャ式から p にアクセスするのを防ぎたい。 import Foundation func foo() { let a = [2, 3, 5] a.withUnsafeBufferPointer { p in DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(3)) { print(p[0]) } } } foo() Thread.sleep(forTimeInterval: 5)
Avatar
omochimetaru 3/13/2018 1:49 AM
エスケープさせたくないってことですか?
Avatar
↑だと a が解放された後にそのバッファのポインタ p にアクセスしちゃってるよね?
Avatar
omochimetaru 3/13/2018 1:51 AM
そうですね、これはだめ
Avatar
↓だと inout だからコンパイルエラーになる。 import Foundation func foo() { var a = [2, 3, 5] a.withUnsafeMutableBufferPointer { p in DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(3)) { print(p[0]) } } } foo() Thread.sleep(forTimeInterval: 5)
Avatar
omochimetaru 3/13/2018 1:52 AM
あ〜、なるほど、inout的にってそういう意味か。
Avatar
withUnsafeBufferPointer はクロージャに渡される引数がそのクロージャ式のスコープの中でのみ有効なのに、せっかく @escaping を区別してるのにコンパイラがそれを強制する術がない。 (edited)
Avatar
omochimetaru 3/13/2018 1:52 AM
え、もう一個のケースでも、pはinoutじゃないのでは?
1:53 AM
普通の引数で型がUnsafeMutableBufferPointerですよね
Avatar
それが inout なんですよ。意味わかんないんだけど。
1:53 AM
あれ?違う??
Avatar
omochimetaru 3/13/2018 1:53 AM
public mutating func withUnsafeMutableBufferPointer<R>(_ body: (inout UnsafeMutableBufferPointer<Array.Element>) throws -> R) rethrows -> R
1:54 AM
ほんとだ、あれ?なにこれ。
Avatar
いや、あってた。
1:54 AM
なんで inout なのかもよくわかんないんだけど、とりあえずそれのおかげで↑の asyncAfter に渡すのはコンパイラが防いでくれる。
1:54 AM
で、この inoutout の除いたようなものがほしいなぁと。
1:55 AM
あと、↓みたいなのも防げるかと。 fooAsync { [weak self] in guard let zelf = self else { return } zelf.foo(...) barAsync { [weak zelf] in // ←この [weak zelf] を忘れないようにしたい guard let zelf = zelf else { return } zelf.bar(...) } }
Avatar
クラッシャー func after(_ fn: @escaping () -> Void) {} func with(_ fn: (inout Int) -> Void ) {} func test() { with { p in after { [p] in } } } (edited)
Avatar
@rintaro それは明示的だから仕方ないですw
2:08 AM
明示的にしかできなくできたらいいかなと。
Avatar
omochimetaru 3/13/2018 7:42 AM
ときどき話題に出てくるCodableとJSONの話で、JSON表現用の型とモデルの型をわけて・・・ってパターン、こうやると少し楽になると気づいた https://gist.github.com/omochi/dec3e819ec7a485e33d43bcdd0c0d84a
Avatar
assoctypeにtypealiasじゃなくてstruct定義でもいいんですね。 言われてみりゃそりゃそうだって感じですけど使ったことなかった。
Avatar
いや、これは暗黙的に推論されてると思う (edited)
Avatar
メソッドのほうからかな?
Avatar
そう
Avatar
試そうとしたんですが最近playgroundsが開かない
7:51 AM
protocol Init { init() } protocol Proto { associatedtype JSON: Init } extension Proto { func hoge() -> JSON { return JSON() } } struct Hoge: Proto { struct JSON { } } こう書いたらtypealias書けって言われますね
👉 1
7:52 AM
あ、Hoge.JSONInit適合してないからだ
Avatar
してないかな
Avatar
: Initつけたら怒られないですね
Avatar
お、そこはそうだ
Avatar
protocol Init { init() } protocol Proto { associatedtype JSON: Init } extension Proto { func hoge() -> JSON { return JSON() } } struct Hoge: Proto { struct JSON: Init, CustomStringConvertible { var description: String = "Hoge.JSON" } } print(Hoge().hoge()) // Hoge.JSON
7:54 AM
こうかな
7:55 AM
hoge()が挿入されて推論されるのかJSONが先にあるのか分からない (edited)
Avatar
protocol Foo { associatedtype Bar } struct Piyo: Foo { struct Bar { } } ありゃ、これ通るから
7:56 AM
動きますね、すごい。昔はこれができなかったような気がします
Avatar
omochimetaru 3/13/2018 7:57 AM
ん?
Avatar
それだけだとassoctypeのBarとPiyo.Barが同一視されてるか微妙だなぁと思ったんですが
Avatar
omochimetaru 3/13/2018 7:57 AM
え、結局、名前でマッチしてた?
Avatar
そうっぽい
8:01 AM
@t.ae 同一視出来ていないとコンパイルが通らないのでこれはOKなきがします
Avatar
あーない場合はtypealias無いって言われますねそういえば
8:01 AM
そんな基本的なことを忘れて長いコードを書いてしまった
Avatar
omochimetaru 3/13/2018 8:02 AM
本題どっか行った
Avatar
encodeToInnerJSONの部分隠蔽できないんですかね
Avatar
omochimetaru 3/13/2018 8:04 AM
隠蔽とは?
Avatar
UserCredentialをそのままJSONEncoderとかにわたせるように
Avatar
omochimetaru 3/13/2018 8:04 AM
なってるよ
8:04 AM
Codableだから
Avatar
あれ?
8:05 AM
ああ一番上から来てるのか
Avatar
omochimetaru 3/13/2018 8:05 AM
そうか、エンコード・デコードのサンプルも書かないとだめだった。
Avatar
I wanted to circle back to this comment from @Joe_Groff: Has there been any recent discussion about this? I’d love for enums to be a bit more ergonomic via optional-chaining. Key path support would be a nice, free bonus! I can imagine it work...
12:48 PM
Avatar
わかる~~
Avatar
この提案みたときは、そんなん必要なときにちょちょいと定義すればええやんけ、って思ったけど・・・
Avatar
苦痛やろ
Avatar
enumを、「A, B, C, Dのどれか」として使おうとしていて、
12:50 PM
Observableでもなんでもいいけど、モナドMにそのenumが入ってるときに
12:50 PM
M<A?> に簡単にmapしたいという需要はあるね
12:51 PM
enumそのまま制御してるときはswitch-caseでいいけど、ヨリ分けてその先別個に何かやるみたいなパターンがあるんだな。
Avatar
なんかまだはっきりとわからないんだけど
12:58 PM
より分けてその先で使いたいパターンっていうのが
12:58 PM
本当にEnumである必要があるのか、について吟味したほうがいいかもしれない。
Avatar
そこはそうだと思うけどねえ
Avatar
omochimetaru 3/15/2018 7:10 AM
@lovee こんなのできた public func recover<R>(_ f: () throws -> R, ifError: (Error) -> R) -> R { do { return try f() } catch let error { return ifError(error) } } public func recover<R>(_ f: () throws -> R, ifError: (Error) throws -> R) throws -> R { do { return try f() } catch let error { return try ifError(error) } }
7:12 AM
この前言っていたguard + tryみたいなパターンは、R をOptional にして使えば guard let x = recover (...) else { return } の形で書けるし、 2つめのオーバーロードを使えば、リカバリできないエラー型の場合はそのまま更に上まで飛んで行く。
7:13 AM
使用例 guard let modelScene = recover({ () -> SCNScene? in try SCNScene(url: url) }, ifError: { error in self.handleError(error) return nil }) else { return }
Avatar
ふむふむ、だいぶ長くなってしまうところ以外は良さげですね 🤔
Avatar
omochimetaru 3/15/2018 7:15 AM
うん、あとOptional推論がうまくいかないから明示しているんだよね
7:16 AM
名前ちょっと変えてかならず Optional になる仕様のほうが使いやすいかも
Avatar
もしかすると ifError のところと最後のところの戻り値は Optional<R> にすべきだったり?
Avatar
omochimetaru 3/15/2018 7:19 AM
あ〜 recover 自体を try? でたたむ手があるな
7:20 AM
guard let modelScene = try? recover({ try SCNScene(url: url) }, ifError: { error in self.handleError(error) throw error }) else { return }
Avatar
できた import SceneKit public func recover <R> (_ f: () throws -> R, ifError: (Error) -> Optional<R>) -> Optional<R> { do { return try f() } catch let error { return ifError(error) } } func test() { let url = URL(fileURLWithPath: "http://www.google.com") guard let _ = recover({ () -> SCNScene in try SCNScene(url: url) }, ifError: { error in print(error) return nil }) else { return } } (edited)
Avatar
omochimetaru 3/15/2018 7:20 AM
これだと型ヒントは消せる (edited)
Avatar
ファイル名対応してないんだDiscord
Avatar
omochimetaru 3/15/2018 7:21 AM
そのパターンでもクロージャの型ヒント消せそう。
7:22 AM
guard let modelScene = recoverToOptional({ try SCNScene(url: url) }, ifError: { error in self.handleError(error) return nil }) else { return }
7:23 AM
行数短くしたいですねえ。
7:24 AM
guard let modelScene = recoverToNone({ try SCNScene(url: url) }, ifError: self.handleError) else { return }
Avatar
よし、ここまで書けた import Foundation public func recover <R> (_ f: () throws -> R, ifError: (Error) -> Void) -> Optional<R> { do { return try f() } catch let error { ifError(error) return nil } } struct Test { let url: URL enum InitError: Error { case unknown } init(urlString: String) throws { guard let url = URL(string: urlString) else { throw InitError.unknown } self.url = url } } func test(_ string: String) { guard let test: Test = recover({ return try Test(urlString: string) }, ifError: { print($0) }) else { return } print(type(of: test)) } test("http://www.google.com") // Test test("") // unknown
Avatar
omochimetaru 3/15/2018 7:33 AM
try TEst のところのreturnいらなそう
7:34 AM
僕はそのrecoverはrecoverToNoneって名前にした
Avatar
まあ1行だけならね
Avatar
nits 第一引数に @autoclosure つけるといいかも
Avatar
↑を読みながら @autoclosure が良さそうだなと思って最後まで読んだら先に言われてた🙄
Avatar
omochimetaru 3/15/2018 8:07 AM
autoclosureもありだけど個人的には何が起きてるかわかりにくくなりそうなので微妙だなあ
Avatar
用途を考えると single-expression closure になることが多いだろうからまさに @autoclosure の出番だと思うけどなぁ。
Avatar
omochimetaru 3/15/2018 8:16 AM
まあ特に標準提案したいというほどの気持ちは無いのでお好みで (edited)
Avatar
多分なんですが
8:19 AM
throwsの値を使って何かするみたいなfunction書くときはそもそもそれをthrowsにして、非throwsとの境界をそこに設定するのが良いのではと思った (edited)
8:21 AM
func doSomething() { return try? doSomething() ?? /* 何か */ } func doSomething() throws { let x = try throwableFunc1() let y = try throwableFunc2() ... } こんなイメジ
Avatar
↑それだとtry?でnilになるから「throwsの値」(飛んでくるエラーオブジェクトの事だよね)が使えない
Avatar
あーー
10:23 AM
ハマり
10:23 AM
たしかにそうだ
Avatar
エラーを使いながらもthrow伝搬を止めて値に畳み込みたいときに、簡単に書くことができないんだよね。do - catch だと式じゃないから式の中に埋め込めないし。 (edited)
Avatar
https://twitter.com/__gfx__/status/974531889817006080 https://twitter.com/omochimetaru/status/974537101004832768 を見て func foo() -> Int { print("Int"); return 1 } func foo() { print("Void") } foo() // error: ambiguous use of 'foo()'
Rubyで「そのメソッドがvoid contextで呼ばれた否か」がとれるといいんだが…(Perlだととれる)。
返り値返さない版を用意したらええのでは・・・(そんなことはわかってるだろうからなんか理由があるんやろうな
Avatar
omochimetaru 3/16/2018 7:59 AM
返り値オーバーロードだ
7:59 AM
なるほど・・・w
Avatar
Void のコンテキストなら下ので確定できたら便利なのかな? (edited)
Avatar
func foo() -> Int { print("Int"); return 1 } func foo() { print("Void") } foo() // error: ambiguous use of 'foo()' _ = foo() // error: ambiguous use of 'foo()' () = foo() // Void 最後の記法がちょっとおもしろい
Avatar
ほほー
Avatar
omochimetaru 3/16/2018 8:02 AM
!w
8:03 AM
_ = foo() なら Void 優先してほしいね。
8:03 AM
いや?それもへんか。
8:03 AM
捨ててるんだからなんかあるのか。
Avatar
それは返り値握りつぶしてる感あるのでむしろIntが呼ばれてそうにみえますね
🙋 1
Avatar
omochimetaru 3/16/2018 8:03 AM
そうですねえ・・・
Avatar
() = ... とかできるのか。 foo()void と解釈してほしいかも。
8:18 AM
@discardableResult との兼ね合いをよく考えないといけなさそうだ。 (edited)
8:19 AM
@discardableResult func foo() -> Int { print("Int"); return 1 } func foo() { print("Void") } foo() // どっちになってほしい? (edited)
Avatar
fooだから分かりにくいですけどガイドラインに従ってればappendappendingとかみたいになるんであんまり問題起こらない気がしますね。
8:22 AM
mutating funcの場合に限るかそれは。
Avatar
今はそもそもがオーバーロードしたときに見分けてくれた方がいいかという前提の話なのでは?
Avatar
うんまぁそうですが
Avatar
実際には問題になるケースが少ないから
8:24 AM
ambiguous でいいんじゃないかってことか。
Avatar
処理内容が同様ならdiscardableResultだけでいいし、処理内容が異なるならオーバーロードするのが間違っている気がします
Avatar
Kishikawa Katsumi 3/16/2018 8:24 AM
コンパイルエラーで全然いいんだけどエラーメッセージをわかりやすくしてほしいと思っています。
Avatar
たぶん元コンテキストのモチベーションとしては、 @discardableResult func foo() -> Int { print("Int"); return 1 } が既にありそれを使っているプロジェクトなんだけど、返値の生成にそれなりの負荷があるので、 func foo() でオーバーロード出来れば、軽量化出来る可能性があると。
Avatar
omochimetaru 3/16/2018 8:25 AM
あと元コンテキストはRubyですね。
Avatar
Kishikawa Katsumi 3/16/2018 8:26 AM
戻り値の型によるオーバーロードを使ったAPIを提供しているSDKをメンテしていた経験でいうと。
Avatar
返値の生成にそれなりの負荷がある
そういうケースはありますね……
Avatar
はい、Ruby はとりあえず無視でw
Avatar
omochimetaru 3/16/2018 8:26 AM
Swiftだったら別に普通に呼び出してる箇所全部リファクタリングできるから別名でオーバーロードで解決しそう・・・
Avatar
Kishikawa Katsumi 3/16/2018 8:28 AM
書き換えが許されるならオーバーロードを作って呼び出し元で戻り値の型を区別するのでもSwiftなら一緒じゃないですか?
8:28 AM
別名をつけなくても。
8:28 AM
どっちがわかりやすいとかは別として。
Avatar
omochimetaru 3/16/2018 8:29 AM
あー、それはそうですね。
Avatar
discardableResult外してVoid overloadでいいじゃん、みたいな気がした
9:13 AM
あ、だめなのか
Avatar
流転してる
Avatar
ぉ、{ [weak self] in guard let self = self else { ... } を認める流れ。
2:36 AM
As discussed in this thread, this patch allows "self" to be an identifier bound to self (see added tests for examples), and is useful in closures where self is weakly captured to avoid re...
Avatar
norio_nomura 3/17/2018 3:04 AM
backtickなしで使える様になるのか。
Avatar
omochimetaru 3/17/2018 6:26 AM
良いね
Avatar
これって一般的なローカル変数として self を使えるようになるわけではない?
1:45 AM
+struct T { + var mutable: Int = 0 + func f() { + // expected-error @+2 {{keyword 'self' cannot be used as an identifier here}} + // expected-note @+1 {{if this name is unavoidable, use backticks to escape it}} + let self = self + } +}
1:48 AM
そうすると、この前話してたキャプチャ禁止を変数にまで拡張したとして、 class Foo { func bar { @noncaptured let self = self baz { self.qux() // Error } } } みたいなことができない。まあ、それが欲しくなったときに認めればいいのか。
Avatar
実装していてパフォーマンスに難があったので何かViewの組み方等でアドバイスをいただければ幸いです。。。 今Swiftでエディターを作っていて、Wordみたいなページ区切りがあるものを実装しています。ただ、このページは入力に応じて高さを拡げていくようにしたい(=文字数の入力制限がない)っていう要求があります。なので、下記構成で作ってみました。 ・UITableView
  • UITableViewCell
    • UITextView
  • UITableViewCell
    • UITextView
UITextViewを拡げていくように作りたいので isScrollable = false にして、入力に応じて動的に拡げていっています。ただ、TextViewへの入力が5000文字とか10000文字になってくると、入力に遅延が発生するようになりました(キーボードをタップして1=2秒後に文字が表示される感じ)。なんとかここをクリアして要求を満たしたいのですが、何か策はありますでしょうか?
Avatar
Kishikawa Katsumi 3/19/2018 8:00 AM
ScrollView(UITableViewやUITextView)は表示されている部分以外を計算しないことによってパフォーマンスを稼いでいます。UITextViewの入力文字が多くなると遅くなるのであれば、何らかの理由により、表示されていない部分も含めた全体の大きさに対して計算が起こっているのだと思います。
Avatar
何らかの理由により、表示されていない部分も含めた全体の大きさに対して計算が起こっている
なるほど、、、これはTextViewのスクロールを禁止しているために、本来のTextViewのパフォーマンスが発揮できていない気がしますね。今のViewの組み方だとできなさそうですね。。。
Avatar
Kishikawa Katsumi 3/19/2018 8:07 AM
5000文字か一万字で高さがどれくらいになるのかわからないですけど、UITableViewで1つのセルが画面の高さより高くなるのであれば、それは速度に大きく影響します。
8:08 AM
UITableViewの手法で計算を省こうとしても画面の大きさ以上の計算をすることになるので。
Avatar
omochimetaru 3/19/2018 8:10 AM
TextViewの中身が増えて画面の縦幅に到達したら、その時点で isScrollable = false をやめて true にして、 TextView自体のサイズは固定したら、見た目にはわかんないけど速度は改善したりしないですかね。
8:11 AM
あーでもテーブルがスクロールする時に通り抜けたりして面倒な事になっちゃいそうだなあ。
Avatar
5000文字か一万字で高さがどれくらいになるのかわからないですけど
画面の高さの10倍でも足りないくらいになったりしますね。。。
8:12 AM
僕もその方法を考えたんですが、おっしゃる通りTableのスクロールの上にTextViewのスクロールがあってすごい使いにくくなっちゃって。どうしたものかという感じです。
Avatar
Kishikawa Katsumi 3/19/2018 8:15 AM
UITextViewに複数のUITextContainerとNSLayoutManagerを使う方法を調べてみるといいと思います。 私が実装するならまず上記の組み合わせで「ページ」という概念が表現できないかやってみます。 でおそらくUITableViewは使わないと思いますが、結果的にUITableViewを使うことになってもUITextContainerとNSLayoutManagerで描画を分割することは必要になると思うので、それは無駄にはならないはずです。
👀 1
Avatar
まず、 UITextViewUITableView から分離して、単体で( isScrollable = false で)パフォーマンスの問題が起こるのかを検証した方が良い気がします。 (edited)
Avatar
UITextViewに複数のUITextContainerとNSLayoutManagerを使う方法を調べてみるといいと思います。
なるほど、調べてみますありがとうございます!
UITextView を UITableView から分離して、単体で( isScrollable = false で)パフォーマンスの問題が起こるのかを検証した方が良い気がします。
単体でもパフォーマンスが下がってしまいます。。。
(edited)
Avatar
それだと UITextView 以外の方法(何がいいかわかりませんが)で実装することができれば UITableView と組み合わせても問題が起こらないかもしれないですね。 (edited)
8:28 AM
たとえば、 UIWebView<textarea> を入れるとかでどうにかできるかもしれません。(それもパフォーマンス低下するかもしれませんし、 view の高さを変更する部分が大変そうな気がしますが) (edited)
Avatar
WebViewのなかでページという概念を表現するイメージですか?それとも上記の構成上のUITextViewをWebViewに置き換えて作るほうですかね?
Avatar
UITextView 相当の、長文でスクロール禁止でもパフォーマンス低下しないものを自力実装するより、 UIWebViewtextarea を入れた方が簡単そうだなと思った思いつきです。ブラウザで長文書いてもそんなにパフォーマンス悪くならない気がしたんですが、あれもスクロール可能だからな気がしますね💧
Avatar
思いつきでもとてもありがたいです!WebViewも見えてない部分は計算しないみたいなのをやってそうなので、うまく行かなさそうな気がしますね。。
Avatar
Kishikawa Katsumi 3/19/2018 8:35 AM
現在ある情報から推測すると、速度が遅くなるのはビューの大きさのせいだと思います。 せっかくなので問題の切り分けをはっきりされると良いと思いますが、UITextViewの isScrollable = falseでビューの大きさが200x200とかで確かめてみるといいと思います。
8:35 AM
^ これは遅くならないはず。
Avatar
さきほど、画面にFitさせる形でTextViewをおいて、そのなかの文字数を10000文字くらいにして、isScrollable = falseでやってみたんですが、遅くなってました〜。。。
Avatar
UITextView ではなく自力実装するなら)原理的には、スクロールの可否に関係なく表示されている領域のみ再描画すれば良いはずだと思うので、スクロールしなくても遅くならないようにできそうな気がします。ただ、長文の途中に文字を挿入すると高さを計算するのにその後の全文字列の大きさを計算しないといけないので重いですかね?
Avatar
Kishikawa Katsumi 3/19/2018 8:37 AM
デバイスはiPhoneですか?iPad?
Avatar
iPhoneです!
Avatar
view の高さを計算する部分を表示されたときに lazy にできるなら、原理的にはスクロールと同じにできそうなので、長文でも遅くならないものを実装できそうに思います。
Avatar
Kishikawa Katsumi 3/19/2018 8:40 AM
iPhoneの画面と同じ大きさのUITextViewなら数万文字を格納したくらいで遅くなることは考えにくいですね。ちょっと検証したコードを見せてもらえませんか?
Avatar
omochimetaru 3/19/2018 8:40 AM
賢いアルゴリズムなら 長い文字列は行区切り表現でもっておいて、行ごとにレイアウト情報をキャッシュしておいて、 編集が発生した箇所よりも上はキャッシュから確定、 編集箇所より下にかけて再計算、行が途切れるところで中断して残りはキャッシュから確定
8:40 AM
ってなりそうだしUITextViewならなってそうだけど
8:41 AM
リアクティブプログラミングになっていて編集イベントからテキスト全文をUITextView.textに再流入させてしまっているとか?
Avatar
そもそも5000文字も1万文字も入力できるスペックを、フルでTableViewに乗せるのはまずい
Avatar
import UIKit class TextViewVC: UIViewController, UITextViewDelegate { @IBOutlet weak var textView: UITextView! override func viewDidLoad() { super.viewDidLoad() setupKeyboardAccessoryView() textView.textContainerInset = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 30) textView.delegate = self textView.isScrollEnabled = false var message = "" for i in 1...10000 { message += "\(i)\n" } textView.text = message } private func setupKeyboardAccessoryView() { let kbToolBar = UIToolbar(frame: CGRect.zero) kbToolBar.barStyle = UIBarStyle.default kbToolBar.sizeToFit() let spacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: self, action: nil) let close = UIBarButtonItem(title: "閉じる", style: .done, target: self, action: #selector(closeKeyboard(sender:))) kbToolBar.items = [spacer, close] textView.inputAccessoryView = kbToolBar } @objc func closeKeyboard(sender: Any) { self.view.endEditing(true) } } (edited)
8:43 AM
Storyboard使ってますが、接続さえすればそのまま動くかと思います。動作確認は実機のiPhoneXでやっています。
8:44 AM
リアクティブは今のところ取り入れていません
🙆 1
Avatar
↓ 4 万文字ほどになってそうですね。 for i in 1...10000 { message += "\(i)\n" }
8:45 AM
改行があるから 5 万か。
Avatar
Kishikawa Katsumi 3/19/2018 8:45 AM
私がすぐに確認できるのは
8:45 AM
textView.textContainerInset = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 30) textView.delegate = self var message = "" for i in 1...10000 { message += "\(i)\n" } textView.text = message この部分だけですけど、これだけだと特に遅くはならないみたいです。
Avatar
とりあえずTableViewの方は、3行まで+末尾とかで実装して、タップしたら別画面のフルスクリーンのTextViewの画面に遷移するのがおすすめです。画面遷移のアニメーションを工夫すれば、ストレスも少なくて済む
Avatar
あ、すいません、isScrollEnabled = falseをStoryboard上からやってしまっていました。 (edited)
Avatar
多分、TableViewCellに載せる事を考えるより、画面遷移のアニメーションを作ったほうがトータルで安いと思います
Avatar
Kishikawa Katsumi 3/19/2018 8:46 AM
^ 上記のテキストを表示しても入力や文字の削除などの操作はストレスなくできます。isScrollable = false/trueにかかわらずです。
Avatar
確かに、要件次第ですが、一般的にはそちらの方が UX も良さそうですね。 < タップしたら別画面のフルスクリーンのTextViewの画面に遷移
Avatar
多分、TableViewCellに載せる事を考えるより、画面遷移のアニメーションを作ったほうがトータルで安いと思います
このへんもデザイナさんと検討中ですが、できれば実現させたいなと思い相談させていただいてました
8:48 AM
上記のテキストを表示しても入力や文字の削除などの操作はストレスなくできます。isScrollable = false/trueにかかわらずです。
for i in 1...10000でもでしょうか??
Avatar
omochimetaru 3/19/2018 8:48 AM
今僕もまるまるコピペで試してみましたけどサクサク動きますね。iPhoneSEです。
Avatar
時間かかってるの
Avatar
omochimetaru 3/19/2018 8:49 AM
iOSすげえな。(内心動かないと思ってた) (edited)
Avatar
Kishikawa Katsumi 3/19/2018 8:49 AM
@moga そうですね。全選択とかカーソル動かしたりとかしてみましたけど。UITextViewの大きさ変わってません?
Avatar
多分 tableView.beginUpdate / tableView.endUpdate なんで
Avatar
Kishikawa Katsumi 3/19/2018 8:49 AM
いや、まあ私としては文字数が原因でないことは確信があって聞いています。
Avatar
こちらだと上記のコード動かしたら、遅くなってるんですが、なぜだ。。。
Avatar
omochimetaru 3/19/2018 8:50 AM
僕の方は UITextViewのレイアウトは Top Left Bottom Right 全部 Parent = 0 でやりました。
Avatar
同じくです
8:51 AM
Avatar
Kishikawa Katsumi 3/19/2018 8:51 AM
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5) { print(textView.frame) } ^のような感じで適当に遅らせてtextViewの大きさを出したらどうなりますか?
Avatar
omochimetaru 3/19/2018 8:52 AM
cs
Avatar
(0.0, 44.0, 375.0, 685.0)
8:52 AM
でした
Avatar
omochimetaru 3/19/2018 8:52 AM
(違うのはSafeArea + iPhoneX ・・・ (edited)
Avatar
Kishikawa Katsumi 3/19/2018 8:53 AM
何でしょうね。サンプルプロジェクトを共有してもらったほうがいいかも。
Avatar
どうしてもやりたい場合の話ですが、巨大なコンテンツを一枚のScrollViewでなんとかする場合
Avatar
ひとまずiPhone8で試してみます
8:54 AM
共有は色々余分なViewが混ざっているので少々お待ちいただければ助かります。
Avatar
最も大きくなる可能性のあるコンテンツをベースに考えると良くって、そうするとTextViewベースに…みたいな話になってきそう。実装時間考えるとあんまり現実案ではないですが。後はWebViewとか。
👀 1
Avatar
omochimetaru 3/19/2018 8:55 AM
共有は色々余分なViewが混ざっているので少々お待ちいただければ助かります
(これを剥がしてシンプルにする過程で症状が解消すると良いな)
Avatar
たしかにwww
Avatar
Kishikawa Katsumi 3/19/2018 8:56 AM
元の要件を考えるとテキストビューにページ区切りの概念ということなので、1つのTextView+ページごとのTextContainerでスッとできると思います。
Avatar
すいません、+αで、ページの間ごとにViewを挟み込んでButtonとか起きたい感じです。。。
Avatar
Kishikawa Katsumi 3/19/2018 8:58 AM
普通に置けると思います。
9:00 AM
ページ単位でビューにするのはまあページ単位のテキストが少ない場合にはシンプルだと思いますけど、1ページの文字数はいくらでもサポートしたいという今回の話だと、結局同じ問題が出てくるので、
Avatar
こちらに置きました。 https://github.com/SeiyaMogami/TextViewTest
Contribute to TextViewTest development by creating an account on GitHub.
Avatar
Kishikawa Katsumi 3/19/2018 9:02 AM
ページ区切りが入力されるまで適当にTextContainerを広げていって、ページ区切りが入力されたら、ページの大きさを確定して下にいくつかのボタンと新しいTextContainerを作る、とかになるんじゃないですかね。
👀 1
Avatar
Simulatorで試しましたが遅かったです。
Avatar
omochimetaru 3/19/2018 9:04 AM
重いw
Avatar
Kishikawa Katsumi 3/19/2018 9:04 AM
遅いですね🤣
9:04 AM
何が違うんだろう。delegateは関係なかったです。
Avatar
本当に何が違うんですかね。。。。。
Avatar
omochimetaru 3/19/2018 9:05 AM
SafeAreaでも無いな
Avatar
Kishikawa Katsumi 3/19/2018 9:06 AM
isScrollEnabledは影響しますね。しかし私たちの検証結果との不一致が説明できない。
Avatar
textView.textContainerInset = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 30)
これは
Avatar
Kishikawa Katsumi 3/19/2018 9:07 AM
関係なさそうです。
Avatar
試しましたが変わりませんでした。
Avatar
Kishikawa Katsumi 3/19/2018 9:07 AM
Storyboardのせいっぽいな。
Avatar
isScrollEnabled を trueにしたらはやくなった
Avatar
omochimetaru 3/19/2018 9:08 AM
すいません、僕は isScrollEnabled = false を入れたら同じ重さになりました
Avatar
Kishikawa Katsumi 3/19/2018 9:09 AM
@omochimetaru Storyboardをやめてみてもらえません? override func viewDidLoad() { super.viewDidLoad() let textView2 = UITextView(frame: view.bounds) textView2.isScrollEnabled = false var message = "" for i in 1...10000 { message += "\(i)\n" } textView2.text = message view.addSubview(textView2) }
Avatar
omochimetaru 3/19/2018 9:09 AM
最初コピペしたときは setupKeyboardAccessoryView() textView.textContainerInset = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 30) textView.delegate = self var message = "" for i in 1...10000 { message += "\(i)\n" } こうだったはず
Avatar
Kishikawa Katsumi 3/19/2018 9:09 AM
さっきのプロジェクトをこう変える。
Avatar
omochimetaru 3/19/2018 9:10 AM
なるほど
Avatar
@omochimetaru すいません、Storyboardで設定してしまっていたのを失念して編集してました
Avatar
岸川さんのコードはAutolayoutの制約がなくなるってことですか?
Avatar
omochimetaru 3/19/2018 9:11 AM
ていうかAutoSizingよね
9:11 AM
@Kishikawa Katsumi 軽くなりました。
Avatar
Kishikawa Katsumi 3/19/2018 9:12 AM
なるほど、AutoLayoutのビュー自体のサイズを求める処理が影響していると。
9:12 AM
それですね、すばらしい。
Avatar
なるほど、、、
Avatar
Kishikawa Katsumi 3/19/2018 9:12 AM
isScrollEnabled = falseだとコンテンツの量=ビューの大きさになるから、かな。
Avatar
これ本コードのほうでやってみますが、結局TableViewにこんな大きいコンテンツを載せるのはそもそもよくないですよね、、、
Avatar
omochimetaru 3/19/2018 9:16 AM
AutoLayoutが効いている場合、例えそれが親ビューの4点固定でレイアウトしているから最終的に関係ないとしても、内部コンテンツのサイズをいったん計算するフローが入ってそこが重い AutoLayoutが無い場合、それが入らなくて軽い、という事ですかね?? (edited)
9:16 AM
マジかコレ
Avatar
Kishikawa Katsumi 3/19/2018 9:17 AM
マニュアルで制約つけてみたけどうまく再現しないですね。
Avatar
omochimetaru 3/19/2018 9:17 AM
あ〜、やってみます。
Avatar
textView = UITextView() self.view.addSubview(textView) textView.translatesAutoresizingMaskIntoConstraints = false textView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true textView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true textView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true textView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true こういうことですか?やってみましたがダメでした。 (edited)
Avatar
omochimetaru 3/19/2018 9:19 AM
@Kishikawa Katsumi override func viewDidLoad() { super.viewDidLoad() let textView2 = UITextView(frame: view.bounds) textView2.isScrollEnabled = false var message = "" for i in 1...10000 { message += "\(i)\n" } textView2.text = message view.addSubview(textView2) func makeCS() { textView2.translatesAutoresizingMaskIntoConstraints = false self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "|[v]|", options: [], metrics: nil, views: ["v": textView2])) self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[v]|", options: [], metrics: nil, views: ["v": textView2])) } makeCS() }
9:19 AM
重くなりました。
9:19 AM
激重で笑うコレ
Avatar
警告は出ないけど、多分外側から大きさ決める部分と、コンテンツから大きさ決まる部分の優先度の解決で問題がある気がする
9:19 AM
Autosizingだとそんなの関係ないからセーフ
Avatar
Kishikawa Katsumi 3/19/2018 9:20 AM
これは遅すぎるな😂
9:21 AM
上下左右のAnchorをSafeAreaとBottomに付けたときは変わらなかったです。
Avatar
omochimetaru 3/19/2018 9:22 AM
translatesAutoresizingMaskIntoConstraints=falseを忘れてないですか?
9:22 AM
AutoSizing, AutoLayoutに変換されてるだけだと思ってたけど、ショートパスあるなら使う意味あるな (edited)
Avatar
AutoLayoutしか使ったことない新参者なんですが、AutoSizingって、制約つけないで、flexibleWidthとかってやるやつですよね?
Avatar
omochimetaru 3/19/2018 9:25 AM
そうです
Avatar
Kishikawa Katsumi 3/19/2018 9:25 AM
@omochimetaru それでした。ありがとうございます。たぶん同じ現象が再現できたはず。
9:25 AM
textView2.translatesAutoresizingMaskIntoConstraints = false textView2.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true textView2.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true textView2.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true textView2.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
Avatar
omochimetaru 3/19/2018 9:26 AM
上下左右のマージンのとり方を、親ビューに対して、固定するかしないかでフラグが4つ、widthとheightを固定するかしないかでフラグが2つ
👀 1
Avatar
Kishikawa Katsumi 3/19/2018 9:26 AM
念のため、Storyboardの方でAutoLayoutのOffなども試したので原因は確定かと思います。
Avatar
TextView+ScrollEnabled=falseでAutolayoutの場合、ContentSizeの計算が入るけど (edited)
9:26 AM
Autoresizingの場合はContentSizeの計算は無いのでそもそも動きが違う気がする (edited)
9:27 AM
フェアにするならtextDidChangeでsizing毎回呼ぶとフェアになる気がするよ
Avatar
AutoResizing使って実現できないか試してみます、みなさん色々Try&Adviceありがとうございました!!
Avatar
Kishikawa Katsumi 3/19/2018 9:32 AM
もしかしてAutoLayoutやめたらTableViewを使った方法でも速度出るのかな。
Avatar
それを今試すだけ試してみようと思っています
Avatar
ContentSize都度計算+tableView.beginUdate/endUpdateで遅くなりそうな予感がしてます
9:33 AM
TableViewCellの高さがTableViewの高さ超えた時にしんどさがあった記憶があるんですが、夢だったかもしれない。
9:33 AM
それはCollectionViewCellの方だったかな…
Avatar
Kishikawa Katsumi 3/19/2018 9:36 AM
TableViewCellの高さがTableViewの高さ超えた時にしんどさ
その通りですね。TableViewのパフォーマンスを稼ぐ手法が役に立たなくなるので。CollectionViewも同様の理由で🙅‍♂️。
(edited)
Avatar
昨晩たまたまメルカリを使っていて気づいたんですが、出品ページの説明文のところに1万文字とか入れても重くなってなくてすごいってなりました。TableViewCellの中にスクロール禁止のTextViewが入ってる感じに見えるんですが、Autolayout使ってないのかな🙄
👀 1
Avatar
swiftc勉強会を開催します。興味ある人は是非参加してください! https://iosdiscord.connpass.com/event/82436/
# わいわいswiftc わいわいswiftcは、Swift Compilerとその周辺技術に関する勉強会です。初心者・上級者を問わず、情報交換とディスカッションの場として機能することを目的としています...
🎉 8
Avatar
ガチ勢無料...
Avatar
protocol Foo { associatedtype Bar func foo<T: HasB>(t: T) where T.B == Bar } protocol HasB { associatedtype B } struct C<E>: Foo { typealias Bar = [E] } この状態でCfooを補完させると func foo<T>(t: T) where T : HasB, [E] == T.B { } というコンパイルの通らないコードが補完される (edited)
5:10 AM
これってどこにissue投げたらいいんですかね
Avatar
bugs.swift.org かな?
Avatar
投げてみます
Avatar
最小ケースを見つけると良さそう
5:15 AM
なんで通らないんだ?と思ったらT.B == [E]なら通るのかw
Avatar
そうなんですよ
5:15 AM
そこで順番が逆になるのがおかしい
Avatar
extension Array { func hoge() -> String { return "Default" } // ① } extension Array where Element == S { func hoge() -> String { return "Subtype" } // ② } extension Array where Element: P { func hoge() -> String { return "Protocol" } // ③ } extension Array where Element == P { func hoge() -> String { return "Existence" } // ④ } [S()].hoge() で②が呼ばれるのって、ここの優先順位が理由ってことで合っていますか? https://github.com/apple/swift/blob/2f6ca48c75cd5482df594496b0be83e7379f2a77/lib/Sema/CSSimplify.cpp#L1830
swift - The Swift Programming Language
5:10 AM
[S()].hoge()swift -frontend -typecheck -debug-constraints に掛けてみると Constraint restrictions: Array<S> to Array<S> is [deep equality] と出ました
Avatar
debug-constraintsの出力みてみると、オーバーロードのどの候補を使うかの比較自体はこの辺りでやってそうな雰囲気ありますね https://github.com/apple/swift/blob/master/lib/Sema/CSRanking.cpp#L387-L725
swift - The Swift Programming Language
Avatar
なるほど、それを利用してる https://github.com/apple/swift/blob/fca77b36598ce1022be09b1d7a23b089a948335f/lib/Sema/CSRanking.cpp#L727-L729 でスコアをつけていって、最終的に "more specific" なoverload が選ばれるみたいですね https://github.com/apple/swift/blob/7e68e02b4eaa1cf44037a383129cbef60ea55d67/docs/TypeChecker.rst#comparing-solutions
swift - The Swift Programming Language
swift - The Swift Programming Language
Avatar
omochimetaru 3/22/2018 2:15 PM
When this lands, generic type aliases will be done - almost - except there’s one more corner case with expression checking: https://t.co/90wKRt8Isc
2:15 PM
@slava_pestov Release Notes Swift 4.2 is the first compiler version to implement Swift 3.0
2:15 PM
At present, the new type node is mainly useful in preserving type sugar for diagnostics purposes, as well as being reflected in other tools (indexing, code completion, etc.).
2:17 PM
ここでも話題に上がってたGenericパラメータを持つTypeAliasの表現を保持するやつができたっぽい コード補完でも使えるって言ってるね
👀 1
Avatar
#swift-2 で話題のバグと組み合わせると盛大に壊れそうでワクワクする (edited)
😓 1
Avatar
omochimetaru 3/26/2018 6:45 AM
Hello Swift Evolution, Over the course of summer of 2017, I was tasked with exploring the implementation of ownership annotations for the Swift language. The goal at the time was to release this proposal at the end of my time and un-underscore ...
6:45 AM
shared 指定子とかのPitchきた
6:51 AM
Grammatical Changes The Swift language will be amended to support the addition of the borrow and consume type annotations. GRAMMAR OF A TYPE ANNOTATION type-annotation → : attributes(opt) inout(opt) type +type-annotation → : attributes(opt) borrow(opt) type +type-annotation → : attributes(opt) consume(opt) type In addition, the grammar of function declarations will be amended to support the consuming attribute. -mutation-modifier → mutating | nonmutating +self-ownership-convention → mutating | nonmutating | consuming
6:52 AM
sharedじゃなくてborrowとconsumeで来た
Avatar
omochimetaru 3/28/2018 4:56 PM
ErrorからNSErrorへのキャスト、Macだと常に成功してLinuxだと失敗することもあるんやな・・・ https://github.com/ReactiveX/RxSwift/blob/master/RxCocoa/Foundation/URLSession%2BRx.swift#L142-L146
RxSwift - Reactive Programming in Swift
Avatar
多分暗黙変換の有無でキャストが常に成功しないことになるのかな
Avatar
omochimetaru 3/29/2018 1:35 PM
Linuxの場合は本当にNSError型のときしか通らない普通のダウンキャストではないかな
1:36 PM
NSError の domain が NSURLErrorDomain のとき、Foundation.URLError 型として扱えるし、なんだか謎が多い
Avatar
protocolをclassに準拠させるの、もしかしてprotocolのassoctypeの制約をwhereで書くようになってからできるようになったのかな
Avatar
Kishikawa Katsumi 3/30/2018 10:28 AM
#waiwai-swiftc とeventの音声チャットで で「わいわいswiftc」にオフライン参加できます。
Avatar
オンラインですね
Avatar
Kishikawa Katsumi 3/30/2018 10:54 AM
そうだ。私たちがオフラインだ。
Avatar
omochimetaru 3/31/2018 4:01 AM
Swift for @TensorFlow Talk video and announcement are up! Check it out: https://t.co/3B4127kbFZ and join the conversation: https://t.co/dNIpVzphLO
Likes
183
4:01 AM
@koher fyi 中身は見てないけど
🙏 1
Avatar
omochimetaru 4/1/2018 3:05 AM
Yesterday we announced Swift for TensorFlow, which applies Swift to the domain of machine learning. The intro video is here: The only additional details available are in a post to our community list, and I encourage ...
Avatar
omochimetaru 4/1/2018 3:12 AM
Draft here: https://github.com/erica/swift-evolution/blob/unwrappable/proposals/XXXX-unwrappable.md Previous discussions: Auto Unwrapping Of Optionals [Pitch] Introducing Unwrappable protocol guard let x = x Introducing an Unwrappable prot...
3:13 AM
これめっちゃ良さそう if letで中身取り出せるのをUnwrappedプロトコルにして、Optionalだけじゃなくてユーザー型でも可能にする案
Avatar
ザーッと流し読みしたら最後の方にしれっとHigherKindedTypeあってワロタ
Avatar
omochimetaru 4/1/2018 3:19 AM
これおもろいね
3:19 AM
Mapped == Selfって制約を足せば
3:19 AM
いわゆるファンクターになるんかな?
Avatar
Selfとは…ってかんじやけど
Avatar
omochimetaru 4/1/2018 3:20 AM
既存の仕様でできないのはassoctypeがパラメタ化してるところだけ
Avatar
Unwrappedだけならいいけど、これが型強制も追加しようとなってくるといよいよやばい
Avatar
omochimetaru 4/1/2018 3:21 AM
スレはif letの事だけど?.とかについても途中で議論されとる
3:22 AM
ああそうか、Self自体は自身のパラメータも含むから
3:22 AM
==Selfたとちょっと変だな
Avatar
Taketo Sano 4/1/2018 2:23 PM
conditional conformance は protocol を一気に二つ上がるとエラーになるっぽいです(?) protocol A { } protocol B: A { } protocol C: B { } struct X<T>: A { } extension X: C where T: Equatable { } // error X<T> does not conform to protocol 'B' protocol A { } protocol B: A { } protocol C: B { } struct X<T>: A { } extension X: B where T: Equatable { } // これを入れる extension X: C where T: Equatable { } // OK (edited)
Avatar
Kishikawa Katsumi 4/1/2018 2:26 PM
@swiftbot protocol A { } protocol B: A { } protocol C: B { } struct X<T>: A { } extension X: C where T: Equatable { }
Avatar
swiftbot BOT 4/1/2018 2:26 PM
@Kishikawa Katsumi, /usercode/main.swift:6:1: error: type 'X<T>' does not conform to protocol 'B' extension X: C where T: Equatable { } ^ /usercode/main.swift:3:10: note: type 'X<T>' does not conform to inherited protocol 'B' protocol C: B { } ^ Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnu
Avatar
Taketo Sano 4/1/2018 2:27 PM
そんな機能がw
Avatar
Kishikawa Katsumi 4/1/2018 2:32 PM
さっき作りました。
Avatar
omochimetaru 4/1/2018 2:32 PM
便利すぎる
Avatar
Taketo Sano 4/1/2018 3:17 PM
typealias も where つきで書けるんですね、便利 public typealias AlgebraicExtension<K, p: _IrreduciblePolynomial> = QuotientRing<Polynomial<K>, PolynomialIdeal<p>> where K == p.K
3:21 PM
conditional conformance を上手く使うとこれまで別の型として定義してたものをただの別名にすることができて気持ちいいですね😚
Avatar
omochimetaru 4/1/2018 3:22 PM
ですねえ〜〜
Avatar
Taketo Sano 4/1/2018 3:23 PM
この機構って他の言語でもあったりするんですか?
Avatar
omochimetaru 4/1/2018 3:25 PM
どうなんだろう・・・
3:26 PM
そもそもconditionalの前にprotocol後付自体が珍しいんですよね
3:29 PM
Rustがいけるっぽい。 impl <A, D> MyTrait<A, D> for YourType where A: TraitB + TraitC, D: TraitE + TraitF {} YourType型が where以下の条件をみたすときに MyTrait<A, D> を conformする
3:30 PM
しかもこの例はGeneric TraitだからSwiftではできない事もしている。
Avatar
Taketo Sano 4/1/2018 3:33 PM
generic trait とはどのようなものなんです?(trait が概ね protocol と思うので良い?)
Avatar
omochimetaru 4/1/2018 3:34 PM
Rustにおけるgenericでない通常のtraitは Swiftにおけるprotocolだと理解して良いと思いますが
3:34 PM
RustのTraitはGenericにできるのに対してSwiftのprotocolはできない
3:34 PM
ここでいうGenericっていうのはジェネリクス型のように型パラメータを取るということで
3:34 PM
↑の例だと <A, D> の部分です。
3:34 PM
Swiftのprotocolには associatedtype という機能がありますが
Avatar
Taketo Sano 4/1/2018 3:35 PM
あぁ、なるほど。
Avatar
omochimetaru 4/1/2018 3:35 PM
これは、あるプロトコルPに適合する型Tが、その適合の過程においてTにおいて関係する型Uを持つことをPの定義として宣言できるというもので
3:35 PM
プロトコルPそれ自体がパラメータをもっているわけではないんですね
Avatar
Taketo Sano 4/1/2018 3:36 PM
はいはい。
Avatar
omochimetaru 4/1/2018 3:36 PM
API documentation for the Rust From trait in crate std.
3:36 PM
ある型Tがジェネリックトレイト From<U>に適合しているとき、 from(U) という関数から T が構築できるっていうのがstdlibにあるんですが (edited)
3:37 PM
これはSwiftだと表現できないんですよねえ。
3:38 PM
Fromトレイトを作ろうとしても、associatedtypeとして一つの型しか示す事ができないから、 Intからも構築できるしStringからも構築できる、みたいにバラバラにできなくて、 SwiftだとFromInt protocol、 FromString protocol って感じで個別に書き下す形になっちゃう。
Avatar
Taketo Sano 4/1/2018 3:40 PM
ふむふむ。
3:40 PM
rust 強い💪🏿
rust 2
Avatar
↑のA,B,Cの一段飛ばしでCをconformするのは、できないのがただしそうです
Avatar
Taketo Sano 4/1/2018 3:41 PM
おっ
Avatar
「Aにconformする」と「Bにconformする」が別で…あれ…
3:42 PM
あれれ、いけるような気もしてきた
Avatar
omochimetaru 4/1/2018 3:43 PM
@swiftbot protocol A {} protocol B : A {} struct S {} extension S : B {} print(S.self is A.Type) print(S.self is B.Type)
Avatar
swiftbot BOT 4/1/2018 3:43 PM
Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnu true true /usercode/main.swift:8:14: warning: 'is' test is always true print(S.self is A.Type) ^ /usercode/main.swift:9:14: warning: 'is' test is always true print(S.self is B.Type) ^
Avatar
omochimetaru 4/1/2018 3:44 PM
@swiftbot protocol A {} protocol B : A {} protocol C : B {} struct S {} extension S : C {} print(S.self is A.Type) print(S.self is B.Type) print(S.self is C.Type)
Avatar
swiftbot BOT 4/1/2018 3:44 PM
Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnu true true true /usercode/main.swift:9:14: warning: 'is' test is always true print(S.self is A.Type) ^ /usercode/main.swift:10:14: warning: 'is' test is always true print(S.self is B.Type) ^ /usercode/main.swift:11:14: warning: 'is' test is always true print(S.self is C.Type) ^
Avatar
omochimetaru 4/1/2018 3:44 PM
conditionalじゃない場合は一気にいける
Avatar
condconfに限り無理なのか
3:46 PM
@swiftbot protocol A {} protocol B : A {} protocol C : B {} struct S<T> {} struct K: A {} extension S : C where T: A {} print(S<K>.self is A.Type) print(S<K>.self is B.Type) print(S<K>.self is C.Type)
Avatar
swiftbot BOT 4/1/2018 3:46 PM
Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnu /usercode/main.swift:8:1: error: type 'S<T>' does not conform to protocol 'B' extension S : C where T: A {} ^ /usercode/main.swift:3:10: note: type 'S<T>' does not conform to inherited protocol 'B' protocol C : B {} ^ /usercode/main.swift:12:17: warning: 'is' test is always true print(S<K>.self is C.Type) ^
Avatar
omochimetaru 4/1/2018 3:47 PM
チケット切っても良さそう
Avatar
3:48 PM
@swiftbot protocol A {} struct S<T> {} struct K: A {} extension S : A where T: A {} print(S<K>.self is A.Type) print(S<S<K>>.self is A.Type) print(S<S<S<K>>>.self is A.Type)
Avatar
swiftbot BOT 4/1/2018 3:48 PM
Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnu true true true /usercode/main.swift:8:17: warning: 'is' test is always true print(S<K>.self is A.Type) ^ /usercode/main.swift:9:20: warning: 'is' test is always true print(S<S<K>>.self is A.Type) ^ /usercode/main.swift:10:23: warning: 'is' test is always true print(S<S<S<K>>>.self is A.Type) ^
Avatar
すごい
Avatar
omochimetaru 4/1/2018 3:49 PM
げげげw
Avatar
Equatableいけるからいけるのわかってるけど、いざやってみて通ると嬉しさがある
Avatar
omochimetaru 4/1/2018 3:50 PM
停止しないパターンは無いのかなあ〜
Avatar
昨日言ってたprotocolを直接拡張するwayがあると、非停止なコンパイルができそう
Avatar
omochimetaru 4/2/2018 1:39 AM
Tensorflow for Swift ではなく Swift for Tensorflow 。自動微分機能やPython相互運用性などを言語自体に組み込むために、コンパイラをforkして別に作るみたい https://t.co/dtfxZkam2B
1:41 AM
Relation to the Swift project This project includes Swift compiler and language changes, which are in a copy of the Swift compiler sources. We think that some of these changes will be interesting to the broader Swift community, including language-integrated automatic differentiation support, a constant expression model, and improved interoperability with Python (and other dynamic languages).
1:41 AM
アップルのSwiftとグーグルのSwiftがどちらもラトナ牽引で分裂するのなんか凄いね・・・
😮 1
Avatar
omochimetaru 4/2/2018 1:58 AM
これがオッケーならSwift for Android作って欲しい
Avatar
@Taketo Sano
この機構って他の言語でもあったりするんですか?
遅レスですが、 Haskell だとできますね。
Avatar
Taketo Sano 4/2/2018 3:59 AM
おぉ、なるほど。
Avatar
Swiftbotこれオープンソースですか?どこで動かしてるんですか
4:50 AM
弊社も導入してみようかな・・・・・・
4:52 AM
おもむろにNSTaskとかFileManagerとか呼んでみるとヤバそう
Avatar
Kishikawa Katsumi 4/2/2018 4:54 AM
@swiftbot contribute
Avatar
swiftbot BOT 4/2/2018 4:54 AM
Contribute to swift-playground development by creating an account on GitHub.
4:54 AM
Contribute to swift-compiler-discord-bot development by creating an account on GitHub.
Avatar
Kishikawa Katsumi 4/2/2018 4:54 AM
ソースコード見たらだいたいわかると思います。
Avatar
おお、まさに必要としていたものだ。弊社でもAWSとかにデプロイしてみます〜
Avatar
Kishikawa Katsumi 4/2/2018 4:56 AM
コンパイルと実行はdockerに閉じ込めていて、時間制限もあるので大した悪事はできないと思います。 しかし何か見つけたら速やかに教えてください。
Avatar
大した悪事はできないと思います
やるなよ、絶対にやるなよ
Avatar
Kishikawa Katsumi 4/2/2018 4:57 AM
dockerfileの名前を決め打ちにしてあるので、それだけ準備が必要です。たぶんあとはそのままいける。
Avatar
snaphost自動更新の仕組みは欲しいですね
4:59 AM
swiftenvとかで新しい奴持ってきてdocker buildする仕組みが
Avatar
floor 使って切り捨てやってたんですけど、以下の結果になるのって Swift 的には正しいんですかね? @swiftbot let x = 9.9499 * 100.0 print("\(x) -> \(floor(x))") // 意図通り let y = 9.95 * 100.0 print("\(y) -> \(floor(y))") // 995.0 になって欲しい (edited)
10:06 AM
994.99 -> 994.0 995.0 -> 994.0
Avatar
omochimetaru 4/2/2018 10:19 AM
@swiftbot let x = 9.9499 * 100.0 print("\(x) -> \(floor(x))") // 意図通り let y = 9.95 * 100.0 print("\(y) -> \(floor(y))") // 995.0 になって欲しい print(y < 995.0)
Avatar
swiftbot BOT 4/2/2018 10:19 AM
Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnu
10:19 AM
/usercode/main.swift:2:18: error: use of unresolved identifier 'floor' print("\(x) -> \(floor(x))") // 意図通り /usercode/main.swift:5:18: error: use of unresolved identifier 'floor' print("\(y) -> \(floor(y))") // 995.0 になって欲しい
Avatar
omochimetaru 4/2/2018 10:19 AM
@swiftbot import Foundation let x = 9.9499 * 100.0 print("\(x) -> \(floor(x))") // 意図通り let y = 9.95 * 100.0 print("\(y) -> \(floor(y))") // 995.0 になって欲しい print(y < 995.0)
Avatar
swiftbot BOT 4/2/2018 10:19 AM
Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnu
10:19 AM
994.99 -> 994.0 995.0 -> 994.0 true
Avatar
omochimetaru 4/2/2018 10:19 AM
@daccchan 正しいです、
10:19 AM
995.0って表示されてるけど
10:20 AM
これ本当は994.999999999 みたいな数字で
10:20 AM
見やすいように切り上げて995.0って出てるけど、内部的には995未満の値なので。
10:20 AM
この現象が起きるのはそもそも「0.95」が2進数であらわせないからです
Avatar
なるほど
10:27 AM
小数点2位以下を切り捨てて、四捨五入しい場合だと、 . で切り離して、少数部分の1文字目だけを取得して再計算するとかっていう方法を取ろうかなんて考えてたんですが、良い方法ってありますか?
Avatar
omochimetaru 4/2/2018 10:29 AM
FloatとDoubleは2進数なので 9.95 は正しく扱えないので、 10進少数のDecimal型を使うのが良いです https://developer.apple.com/documentation/foundation/decimal (edited)
10:30 AM
@swiftbot
10:30 AM
@swiftbot import Foundation let a = Decimal(string: "9.95")! * Decimal(string: "100")! print(Decimal(string: "995")! == a)
Avatar
swiftbot BOT 4/2/2018 10:31 AM
Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnu
10:31 AM
true
Avatar
omochimetaru 4/2/2018 10:31 AM
定数を初期化するときは文字列経由でやらないと、途中でFloatを通ると意味が無いので注意です
Avatar
なるほど Decimal を使うんですか。 ちょっと試してみます。 ありがとうございますー
Avatar
Taketo Sano 4/3/2018 2:28 AM
cond. conf. で protocol を二つ以上上がれない問題は、継承の順序通りに書けばいけることが分かりました。 @swiftbot protocol A { } protocol B: A { } protocol C: B { } struct X<T>: A { } // extension X: C where T: Equatable { } // これだとエラー extension X: B, C where T: Equatable { } // これなら OK (edited)
Avatar
swiftbot BOT 4/3/2018 2:28 AM
Swift version 4.1 (swift-4.1-RELEASE)
2:28 AM
/usercode/main.swift:8:41: error: invalid character in source file extension X: B, C where T: Equatable { }  // これなら OK
Avatar
@swiftbot class X { var a: Int init(a: Int) { self.a = a } } protocol A { var b: String { get } } extension A { var b: String { return "hello" } } extension X: A { } class Y: X { init() { print(b) super.init(a: 1) } }
Avatar
swiftbot BOT 4/4/2018 7:20 AM
Swift version 4.1 (swift-4.1-RELEASE)
7:20 AM
/usercode/main.swift:22:15: error: 'self' used before 'super.init' call print(b) ^
Avatar
@swiftbot --version 4.0.3 class X { var a: Int init(a: Int) { self.a = a } } protocol A { var b: String { get } } extension A { var b: String { return "hello" } } extension X: A { } class Y: X { init() { print(b) super.init(a: 1) } }
Avatar
swiftbot BOT 4/4/2018 7:20 AM
Swift version 4.0.3 (swift-4.0.3-RELEASE)
7:20 AM
/usercode/main.swift:22:15: error: 'self' used before super.init call print(b) ^
Avatar
アレ
7:20 AM
4.0.3だと通ると思ったが…
Avatar
omochimetaru 4/5/2018 9:44 AM
@swiftbot enum AA { case aa(p1: Int, p2: String) } let a = AA.aa(p1: 1, p2: "p2") switch a { case .aa(p3: let str): print(type(of: str)) }
Avatar
swiftbot BOT 4/5/2018 9:44 AM
Swift version 4.1 (swift-4.1-RELEASE)
9:44 AM
(p1: Int, p2: String)
Avatar
omochimetaru 4/5/2018 9:45 AM
ラベル付きタプルに対するパターンマッチのときのラベル部分に意味はない・・・?
Avatar
無い気がする
Avatar
omochimetaru 4/5/2018 9:46 AM
数があってるときは怒られるな
9:46 AM
1個だけ書いたときが変な挙動
Avatar
@swiftbot (p1: Int, p2: String).self is (p3: Int, p4: String).Type
Avatar
swiftbot BOT 4/5/2018 9:47 AM
Swift version 4.1 (swift-4.1-RELEASE)
9:47 AM
/usercode/main.swift:1:28: warning: expression of type 'Bool' is unused (p1: Int, p2: String).self is (p3: Int, p4: String).Type ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Avatar
print忘れてた
9:47 AM
@swiftbot print((p1: Int, p2: String).self is (p3: Int, p4: String).Type)
Avatar
swiftbot BOT 4/5/2018 9:47 AM
Swift version 4.1 (swift-4.1-RELEASE)
9:47 AM
false
Avatar
あれーまじか
Avatar
omochimetaru 4/5/2018 9:48 AM
@swiftbot enum AA { case aa(p1: Int, p2: String) } let a = AA.aa(p1: 1, p2: "p2") switch a { case .aa(p3: let x, p4: let str): print(type(of: str)) }
Avatar
swiftbot BOT 4/5/2018 9:48 AM
Swift version 4.1 (swift-4.1-RELEASE)
9:48 AM
/usercode/main.swift:8:10: error: tuple pattern element label 'p3' must be 'p1' case .aa(p3: let x, p4: let str): ^
Avatar
omochimetaru 4/5/2018 9:48 AM
2個かいてるときはラベルもちゃんとしないとだめ
Avatar
なるなるほどほど
9:50 AM
てかそれは、AssociatedValueが複数の時に変なのでは
Avatar
omochimetaru 4/5/2018 9:50 AM
case側がAssoc1個のときは
Avatar
tupleへの変換が走って謎のラベルが許されてるように見える
Avatar
omochimetaru 4/5/2018 9:50 AM
常にガバガバ?
Avatar
そっちはtupleへの変換起きないから怒られるのではと思う
Avatar
1個と2個で動き違うの面白い
10:43 AM
パターンマッチの方ではラベル書かない派です。それはバインドする変数名で説明すればいいと思う。
Avatar
omochimetaru 4/5/2018 10:44 AM
それだとcaseにassociated valueが追加されたり順番が入れ替わったときに
10:44 AM
変更が検知できないのが気になる
10:45 AM
(1個から2個の場合、↑であげた謎挙動のせいでマッチは成功する、その先で型が壊れるので止まるが)
Avatar
なるほど?
10:46 AM
謎挙動そこで影響してくるか
Avatar
omochimetaru 4/5/2018 10:46 AM
もともとそれで気づいたのです・・・
10:46 AM
まあ、たとえば、Intが2個の場合に、定義順入れ替えは検出できないですよね。
Avatar
普段そこまで考えてないな……
Avatar
omochimetaru 4/5/2018 10:47 AM
でも case .image(url: let url): は冗長でダサいのはそうなんですよねえ。
Avatar
順番入れ替えとか気にする必要があるならstructにしちゃうのが確実か
Avatar
omochimetaru 4/5/2018 10:54 AM
確かにstruct1個持ったcaseにすると確実ですね
Avatar
僕はinner struct推しですね、諸々トータルで良い塩梅
Avatar
omochimetaru 4/6/2018 7:32 AM
この記事が良かったので @hachiware さんをここに勧誘しました。 https://qiita.com/creaaa/items/4297bf60d222d661498f
Xcode 9.3 正式版が一向にリリースされないため、しびれを切らして投稿します。 (追記) -> 翌日にリリース来ました。念願のSwift 4.1や。**Swift 4.1の次はSwift 4.2で、その次はSwift ...
7:34 AM
記事中で @Kuniwak の「CCなくて不便」って記事が参照されていて、そんな記事あったっけ〜と思って読みにいったら、 2016年12月に、自分が「Acceptedしてるから待とう」ってコメントしてたw 16ヶ月後、そこには元気なCondConf搭載のXcodeちゃんが配信されていたのでした・・・
Avatar
来週の Swift Tweets の発表内容と大分被ってるなw
7:43 AM
まあでも今更内容変更して準備するのは無理だし、説明の仕方は色々あってもいいのでそのままのテーマでいきます。
👍 1
Avatar
omochimetaru 4/6/2018 7:43 AM
おおもうすぐ
7:44 AM
cond-confのテーマなんですか、Xcode配布と合わせてタイミング予測が完璧w
Avatar
本番までに 4.1 出ないんじゃないかとヒヤヒヤしたw
Avatar
omochimetaru 4/6/2018 7:58 AM
Avatar
@swiftbot class _Foo { class func get() -> _Foo { return _Foo() } } class Foo<X>: _Foo { override class func get() -> _Foo { return Foo() } } protocol Bar {} extension Foo where X: _Foo, X: Bar { static func make() -> Foo { return get() as! Foo } } Casting always failって出るけど嘘のパターン見つけた
Avatar
swiftbot BOT 4/9/2018 10:09 AM
Swift version 4.1 (swift-4.1-RELEASE)
10:09 AM
/usercode/main.swift:12:22: warning: cast from '_Foo' to unrelated type 'Foo<X>' always fails return get() as! Foo ~~~~~ ^ ~~~
Avatar
conditional extensionでconditionにclassとprotocolを制約付けたGenerics型とのキャストで発生する
10:14 AM
@swiftbot --version=4.0.3 class _Foo { class func get() -> _Foo { return _Foo() } } class Foo<X>: _Foo { override class func get() -> _Foo { return Foo() } } protocol Bar {} extension Foo where X: _Foo, X: Bar { static func make() -> Foo { return get() as! Foo } }
Avatar
swiftbot BOT 4/9/2018 10:14 AM
Swift version 4.0.3 (swift-4.0.3-RELEASE)
10:14 AM
/usercode/main.swift:12:22: warning: cast from '_Foo' to unrelated type 'Foo<X>' always fails return get() as! Foo ~~~~~ ^ ~~~
Avatar
ありゃー前からだったか(´・ω・`)
Avatar
https://medium.com/@slavapestov/behind-the-scenes-improvements-in-swift-4-1-269dd56e30c2 Swift 4.1 でのリリースノートに載っていない変更などを Slava が解説しています。
Swift 4.1 has been released, and as you can see from the release announcement, there are many important user-visible improvements…
👍 1
Avatar
Classes conforming to protocols with default implementations
12:35 AM
static funcでSelf返すデフォルト実装を持っていても、final classにしなくてよくなったのかな
12:36 AM
4.0以前でもinitならokだった
Avatar
norio_nomura 4/12/2018 1:06 AM
その記事読んでちょうど今試してた。 (edited)
Avatar
omochimetaru 4/12/2018 1:08 AM
あれ?それ何かおかしなことにならないのか。
Avatar
大丈夫と思うよ
Avatar
omochimetaru 4/12/2018 3:35 AM
protocolのweak varのweakいらなくなったのもSwift4.1か
Avatar
こんにちは、AIプラットフォームClova開発チームのezuraです。この記事はLINE Advent Calendar 2017の14日目の記事です。 みなさん、今年のSwift...
Avatar
omochimetaru 4/12/2018 3:44 AM
あ、それだ。
3:44 AM
なんかとっくに無くなった気がしていたんだけど、最近書いてみたら書けたので、あれ?って思ってた。
3:44 AM
4.0まではweakつけられたんやなと
3:45 AM
さっきxcode新しくしたら警告が出たから4.1だったのかーと。
Avatar
omochimetaru 4/12/2018 5:57 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
5:57 AM
めちゃめちゃ話し合ってた乱数APIがレビュー入りしてた
Avatar
omochimetaru 4/12/2018 6:15 AM
自然で使いやすそう
🙂 3
Avatar
@swiftbot protocol P { associatedtype X = Int func f(_ x: X) } extension P where Self == S { func f(_ x: X) {} } struct S: P { func f(_ x: X) {} }
Avatar
Swift version 4.1 (swift-4.1-RELEASE)
12:33 PM
/usercode/main.swift:13:17: error: reference to invalid associated type 'X' of type 'S' func f(_ x: X) {} ^
Avatar
@swiftbot protocol P { associatedtype X = Int func f(_ x: X) } extension P { func f(_ x: X) {} } struct S: P { func f(_ x: X) {} }
Avatar
Swift version 4.1 (swift-4.1-RELEASE)
Avatar
@swift403 --versions=latest protocol P { associatedtype X = Int func f(_ x: X) } extension P where Self == S { func f(_ x: X) {} } struct S: P { func f(_ x: X) {} }
Avatar
exit status: 1, error output: <unknown>:0: error: unknown argument: '--versions=latest'
Avatar
@swiftbot --version=latest protocol P { associatedtype X = Int func f(_ x: X) } extension P where Self == S { func f(_ x: X) {} } struct S: P { func f(_ x: X) {} }
Avatar
Swift version 4.2-dev (LLVM 8a97de0e52, Clang 3c973cd6c1, Swift e0c091a012)
12:36 PM
/usercode/main.swift:13:17: error: reference to invalid associated type 'X' of type 'S' func f(_ x: X) {} ^
Avatar
壊れた
12:37 PM
where Self == Sで何が変わるんだろう
Avatar
@swiftbot protocol P { associatedtype X = Int func f1(_ x: X) func f2(_ x: X) } struct S: P { func f1(_ x: X) {} func f2(_ x: X) {} }
Avatar
swiftbot BOT 4/16/2018 7:12 AM
Swift version 4.1 (swift-4.1-RELEASE)
7:12 AM
/usercode/main.swift:11:18: error: reference to invalid associated type 'X' of type 'S' func f2(_ x: X) {} ^
Avatar
デフォルト型を持つassoctypeをシグネチャに持つやつを2個実装するとダメ? (edited)
Avatar
それっぽいですね
8:56 AM
witness table周りがバグってる?
Avatar
SR-6516 は associatedtype が他の associatedtype を参照している時の話なので、ちょっと違うと思います。これはこれでバグ報告しておいた方が良さそうです。
🙇 1
Avatar
なるほど、ありがとうございます!バグ報告投げようと思います。
Avatar
CodableのkeyDecodingStrategy,
11:45 AM
これとCodingKeyを組み合わせて、
11:45 AM
CodingKeyを明記する方にsnake_caseを混ぜるとデコードに失敗して、その時のエラーメッセージがキーが見つからないよ~としか出てこないので1時間近くハマりがあった
11:46 AM
camelCaseにするとデコード成功するけどこれはなかなか
Avatar
CodableをGenericsでやろうとすると、OptionalがGenericsの有無で、キー無しが通るかどうかの挙動が変わる事を発見した
6:03 AM
発見したくなかった…
6:04 AM
struct X<T: Codable>: Codable { var t: T }; typealias A = X<Int?> struct A: Codable { var t: Int? } この2つの挙動が違う (edited)
Avatar
omochimetaru 4/24/2018 6:06 AM
なるほど・・・
Avatar
CondConfは半ば適応されていてこいつはまだちゃんと動かないということかな
Avatar
assoctypeのフィールド由来のtypealias省略マッチング、個数に限界があって限界を超えるとコンパイルが終わらなくなることがわかった
6:55 AM
30個ぐらいやると無限にコンパイルが終わらない
Avatar
norio_nomura 4/25/2018 3:53 AM
swift-4.2-DEVELOPMENT-SNAPSHOT-2018-04-23-aが出てる。
Avatar
omochimetaru 4/25/2018 4:12 AM
Codable絡みのコンパイラのバグ見つけた
4:13 AM
あとで @t.ae が投稿します
Avatar
// OK struct Var: Codable { static var name: String { return "namae" } var name: String init(name: String) { self.name = name } } // NG struct Property: Codable { static let name: String = "namae" var name: String init(name: String) { self.name = name } }
Avatar
omochimetaru 4/25/2018 4:49 AM
@swiftbot struct Property: Codable { static let name: String = "namae" var name: String init(name: String) { self.name = name } }
🛠 1
Avatar
swiftbot BOT 4/25/2018 4:49 AM
Swift version 4.1 (swift-4.1-RELEASE)
4:49 AM
swift: /home/buildnode/jenkins/workspace/oss-swift-4.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::MetatypeType, Y = swift::TypeBase]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed. /usr/bin/swift[0x3f24d54] /usr/bin/swift[0x3f25096] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f3c457f8390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7f3c43f37428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7f3c43f3902a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7f3c43f2fbd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7f3c43f2fc82] /usr/bin/swift[0x5f332c] /usr/bin/swift[0xc6c474] /usr/bin/swift[0xc80ca8] /usr/bin/swift[0xc77e4c] /usr/bin/swift[0xc6eff8] /usr/bin/swift[0xcf6b1a] /usr/bin/swift[0xcf74c6] /usr/bin/swift[0xcf620a] /usr/bin/swift[0xcf55ab] /usr/bin/swift[0xcf4e80] /usr/bin/swift[0xce08fc] /usr/bin/swift[0xcdf3dc] /usr/bin/swift[0xc74274] /usr/bin/swift[0xc78307] /usr/bin/swift[0xc6f45b] /usr/bin/swift[0xcc12b1] /usr/bin/swift[0xcc106e] /usr/bin/swift[0xc8fec5] /usr/bin/swift[0xc33515] /usr/bin/swift[0xc32021] /usr/bin/swift[0xc3221d] /usr/bin/swift[0x4c27c4] /usr/bin/swift[0x4beecc] /usr/bin/swift[0x4778c4] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f3c43f22830] /usr/bin/swift[0x475179] Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret /usercode/main.swift -disable-objc-interop -I /usr/lib/swift/clang/include/ -I /vendor/SwiftyMath/.build/release/ -I /vendor/swift-package-libbsd/ -module-name main -ldSwiftyMath 1. While silgen emitFunction SIL function "@_T04main8PropertyV6encodeys7Encoder_p2to_tKF". for 'encode(to:)' in module 'main' Aborted (core dumped)
Avatar
XCodeと違う壊れ方してますね
Avatar
omochimetaru 4/25/2018 4:49 AM
@swift-4.1.3 struct Property: Codable { static let name: String = "namae" var name: String init(name: String) { self.name = name } }
Avatar
exit status: 134 with stderr:swift: /home/buildnode/jenkins/workspace/oss-swift-4.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::MetatypeType, Y = swift::TypeBase]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed. #0 0x0000000003f24d54 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x3f24d54) #1 0x0000000003f25096 SignalHandler(int) (/usr/bin/swift+0x3f25096) #2 0x00007f63ee8e4390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #3 0x00007f63ed023428 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35428) #4 0x00007f63ed02502a abort (/lib/x86_64-linux-gnu/libc.so.6+0x3702a) #5 0x00007f63ed01bbd7 (/lib/x86_64-linux-gnu/libc.so.6+0x2dbd7) #6 0x00007f63ed01bc82 (/lib/x86_64-linux-gnu/libc.so.6+0x2dc82) #7 0x00000000005f332c (/usr/bin/swift+0x5f332c) #8 0x0000000000c6c474 swift::Lowering::SILGenFunction::emitRValueForStorageLoad(swift::SILLocation, swift::Lowering::ManagedValue, swift::CanType, bool, swift::AbstractStorageDecl*, swift::Lowering::RValue, llvm::ArrayRef<swift::Substitution>, swift::AccessSemantics, swift::Type, swift::Lowering::SGFContext, bool) (/usr/bin/swift+0xc6c474) #9 0x0000000000c80ca8 (anonymous namespace)::NominalTypeMemberRefRValueEmitter::emit(swift::Lowering::SILGenFunction&) (/usr/bin/swift+0xc80ca8) #10 0x0000000000c77e4c swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) (/usr/bin/swift+0xc77e4c) #11 0x0000000000c6eff8 swift::Lowering::SILGenFunction::emitRValueAsSingleValue(swift::Expr*, swift::Lowering::SGFContext) (/usr/bin/swift+0xc6eff8) #12 0x0000000000cf6b1a (anonymous namespace)::ArgEmitter::emit(swift::Lowering::ArgumentSource&&, swift::Lowering::AbstractionPattern) (/usr/bin/swift+0xcf6b1a) #13 0x0000000000cf74c6 (anonymous namespace)::ArgEmitter::emitExpanded
Avatar
omochimetaru 4/25/2018 4:49 AM
@swift-4.2.4 struct Property: Codable { static let name: String = "namae" var name: String init(name: String) { self.name = name } }
Avatar
exit status: 134 with stderr:swift: /home/buildnode/jenkins/workspace/oss-swift-4.2-package-linux-ubuntu-16_04/llvm/include/llvm/Support/Casting.h:255: typename cast_retty<X, Y *>::ret_type llvm::cast(Y *) [X = swift::MetatypeType, Y = swift::TypeBase]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed. #0 0x00000000040df5b4 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x40df5b4) #1 0x00000000040df8f6 SignalHandler(int) (/usr/bin/swift+0x40df8f6) #2 0x00007fcd0eafc390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #3 0x00007fcd0d23b428 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35428) #4 0x00007fcd0d23d02a abort (/lib/x86_64-linux-gnu/libc.so.6+0x3702a) #5 0x00007fcd0d233bd7 (/lib/x86_64-linux-gnu/libc.so.6+0x2dbd7) #6 0x00007fcd0d233c82 (/lib/x86_64-linux-gnu/libc.so.6+0x2dc82) #7 0x00000000005fecaf (/usr/bin/swift+0x5fecaf) #8 0x0000000000c98bc7 swift::Lowering::SILGenFunction::emitRValueForStorageLoad(swift::SILLocation, swift::Lowering::ManagedValue, swift::CanType, bool, swift::AbstractStorageDecl*, swift::Lowering::RValue, llvm::ArrayRef<swift::Substitution>, swift::AccessSemantics, swift::Type, swift::Lowering::SGFContext, bool) (/usr/bin/swift+0xc98bc7) #9 0x0000000000cb3a6b (anonymous namespace)::NominalTypeMemberRefRValueEmitter::emit(swift::Lowering::SILGenFunction&) (/usr/bin/swift+0xcb3a6b) #10 0x0000000000caa3f0 swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) (/usr/bin/swift+0xcaa3f0) #11 0x0000000000c9b8a8 swift::Lowering::SILGenFunction::emitRValueAsSingleValue(swift::Expr*, swift::Lowering::SGFContext) (/usr/bin/swift+0xc9b8a8) #12 0x0000000000d283ed (anonymous namespace)::ArgEmitter::emit(swift::Lowering::ArgumentSource&&, swift::Lowering::AbstractionPattern) (/usr/bin/swift+0xd283ed) #13 0x0000000000d28e34 (anonymous namespace)::ArgEmitter::emitExpanded
Avatar
@swiftbot import Foundation struct User: Codable { static var name: String { return "user" } var name: String } let u = User(name: "hoge") let a = try! JSONEncoder().encode(u) print(String.init(data: a, encoding: .utf8))
🛠 1
Avatar
swiftbot BOT 4/26/2018 2:28 AM
Swift version 4.1 (swift-4.1-RELEASE)
2:28 AM
/usercode/main.swift:10:7: warning: expression implicitly coerced from 'String?' to Any print(String.init(data: a, encoding: .utf8)) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usercode/main.swift:10:14: note: provide a default value to avoid this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ?? <#default value#> /usercode/main.swift:10:14: note: force-unwrap the value to avoid this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! /usercode/main.swift:10:14: note: explicitly cast to Any with 'as Any' to silence this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ as Any swift: /home/buildnode/jenkins/workspace/oss-swift-4.1-package-linux-ubuntu-16_04/swift/lib/SILGen/RValue.cpp:533: void swift::Lowering::RValue::forwardInto(swift::Lowering::SILGenFunction &, swift::SILLocation, swift::Lowering::Initialization *) &&: Assertion `isPlusOne(SGF) && "Can not forward borrowed RValues"' failed. /usr/bin/swift[0x3f24d54] /usr/bin/swift[0x3f25096] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f582f9c3390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7f582e102428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7f582e10402a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7f582e0fabd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7f582e0fac82] /usr/bin/swift[0xcd7ac0] /usr/bin/swift[0xccee92] /usr/bin/swift[0xc5450f] /usr/bin/swift[0xccf200] /usr/bin/swift[0xcf6d60] /usr/bin/swift[0xcf55ab] /usr/bin/swift[0xcf4e80] /usr/bin/swift[0xce08fc] /usr/bin/swift[0xce8a68] /usr/bin/swift[0xca1799] /usr/bin/swift[0xc9dd66] /usr/bin/swift[0xc79460] /usr/bin/swift[0xc6eff8] /usr/bin/swift[0xcf6b1a] /usr/bin/swift[0xcf74c6] /usr/bin/swift[0xcf620a] ...
2:28 AM
2.76 KB
Avatar
あれ?手元では以下の出力でしたが Optional("{\"name\":\"user\"}")
Avatar
omochimetaru 4/26/2018 2:29 AM
@swiftbot import Foundation struct User: Codable { var name: String } let u = User(name: "hoge") let a = try! JSONEncoder().encode(u) print(String.init(data: a, encoding: .utf8))
🛠 1
Avatar
swiftbot BOT 4/26/2018 2:29 AM
Swift version 4.1 (swift-4.1-RELEASE)
2:29 AM
Optional("{\"name\":\"hoge\"}")
2:29 AM
/usercode/main.swift:9:7: warning: expression implicitly coerced from 'String?' to Any print(String.init(data: a, encoding: .utf8)) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usercode/main.swift:9:14: note: provide a default value to avoid this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ?? <#default value#> /usercode/main.swift:9:14: note: force-unwrap the value to avoid this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! /usercode/main.swift:9:14: note: explicitly cast to Any with 'as Any' to silence this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ as Any
Avatar
omochimetaru 4/26/2018 2:29 AM
@swiftbot import Foundation struct User: Codable { static var name: String { return "user" } var name: String } let u = User(name: "hoge") let a = try! JSONEncoder().encode(u) print(String.init(data: a, encoding: .utf8))
🛠 1
Avatar
swiftbot BOT 4/26/2018 2:30 AM
Swift version 4.1 (swift-4.1-RELEASE)
2:30 AM
/usercode/main.swift:10:7: warning: expression implicitly coerced from 'String?' to Any print(String.init(data: a, encoding: .utf8)) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usercode/main.swift:10:14: note: provide a default value to avoid this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ?? <#default value#> /usercode/main.swift:10:14: note: force-unwrap the value to avoid this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! /usercode/main.swift:10:14: note: explicitly cast to Any with 'as Any' to silence this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ as Any swift: /home/buildnode/jenkins/workspace/oss-swift-4.1-package-linux-ubuntu-16_04/swift/lib/SILGen/RValue.cpp:533: void swift::Lowering::RValue::forwardInto(swift::Lowering::SILGenFunction &, swift::SILLocation, swift::Lowering::Initialization *) &&: Assertion `isPlusOne(SGF) && "Can not forward borrowed RValues"' failed. /usr/bin/swift[0x3f24d54] /usr/bin/swift[0x3f25096] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7fc32e218390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7fc32c957428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7fc32c95902a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7fc32c94fbd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7fc32c94fc82] /usr/bin/swift[0xcd7ac0] /usr/bin/swift[0xccee92] /usr/bin/swift[0xc5450f] /usr/bin/swift[0xccf200] /usr/bin/swift[0xcf6d60] /usr/bin/swift[0xcf55ab] /usr/bin/swift[0xcf4e80] /usr/bin/swift[0xce08fc] /usr/bin/swift[0xce8a68] /usr/bin/swift[0xca1799] /usr/bin/swift[0xc9dd66] /usr/bin/swift[0xc79460] /usr/bin/swift[0xc6eff8] /usr/bin/swift[0xcf6b1a] /usr/bin/swift[0xcf74c6] /usr/bin/swift[0xcf620a] ...
2:30 AM
2.76 KB
Avatar
omochimetaru 4/26/2018 2:30 AM
同名のstatic varがあるとCodableが壊れまくるな
Avatar
やばい
Avatar
omochimetaru 4/26/2018 2:30 AM
@tarunon 昨日のはこれで init の網羅検査が壊れる話だったんだけど
2:30 AM
そっちはcomputed propertyにすれば解決したんだが
Avatar
Vaporがstatic let nameを要求しつつDBにもnameというカラムがあるのでやばひ
Avatar
omochimetaru 4/26/2018 2:31 AM
今度は今日、encodeするときにstaticなcomputed propertyで上書きされるので
2:31 AM
どうにもならない、Linuxにおいては実行時クラッシュ
2:31 AM
@swift-4.0.3 import Foundation struct User: Codable { static var name: String { return "user" } var name: String } let u = User(name: "hoge") let a = try! JSONEncoder().encode(u) print(String.init(data: a, encoding: .utf8))
Avatar
stderr:main.swift:10:7: warning: expression implicitly coerced from 'String?' to Any print(String.init(data: a, encoding: .utf8)) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ main.swift:10:14: note: provide a default value to avoid this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ?? <#default value#> main.swift:10:14: note: force-unwrap the value to avoid this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! main.swift:10:14: note: explicitly cast to Any with 'as Any' to silence this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ as Any TYPE MISMATCH IN ARGUMENT 0 OF APPLY AT expression at [<invalid loc> - <invalid loc>] argument value: %1 = argument of bb0 : $User // user: %3 parameter type: $@thin User.Type #0 0x0000000003ae91b8 llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/usr/bin/swift+0x3ae91b8) #1 0x0000000003ae98f6 SignalHandler(int) (/usr/bin/swift+0x3ae98f6) #2 0x00007f92b5289390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #3 0x00007f92b39c8428 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35428) #4 0x00007f92b39ca02a abort (/lib/x86_64-linux-gnu/libc.so.6+0x3702a) #5 0x0000000000c648e5 swift::Lowering::SILGenFunction::emitApply(std::unique_ptr<swift::Lowering::ResultPlan, std::default_delete<swift::Lowering::ResultPlan> >&&, swift::Lowering::ArgumentScope&&, swift::SILLocation, swift::Lowering::ManagedValue, llvm::ArrayRef<swift::Substitution>, llvm::ArrayRef<swift::Lowering::ManagedValue>, swift::Lowering::CalleeTypeInfo const&, swift::Lowering::ApplyOptions, swift::Lowering::SGFContext) (/usr/bin/swift+0xc648e5) #6 0x0000000000c66f09 (anonymous namespace)::CallEmission::apply(swift::Lowering::SGFContext) (/usr/bin/swift+0xc66f09
Avatar
omochimetaru 4/26/2018 2:31 AM
4.0もだめか
Avatar
最近モデル周りガチャガチャやってるから
Avatar
omochimetaru 4/26/2018 2:32 AM
う〜む
Avatar
エンコードもテスト書いておくか、あぶねー
Avatar
omochimetaru 4/26/2018 2:32 AM
普通はinstance propertyしか使わないから気づかなかったが
2:32 AM
class/static propertyとの絡みがヤバそうだ
2:32 AM
vapor がそれでモデルのテーブル名とかをコントロールしてて
2:32 AM
テーブル名APIとしてのnameと、カラムのnameがぶつかってるんだよねw
😲 1
Avatar
ハハァ
2:33 AM
死ぬじゃん
Avatar
omochimetaru 4/26/2018 2:33 AM
死ぬw
Avatar
てかテーブル名をnameは衝突するからやめれ
Avatar
omochimetaru 4/26/2018 2:33 AM
いや、
Avatar
vaporが
Avatar
omochimetaru 4/26/2018 2:33 AM
static var name { "user" } var name = "tarunon"
2:33 AM
こういうこと。
Avatar
vaporのapiがわるい
Avatar
omochimetaru 4/26/2018 2:33 AM
そうかなあw
Avatar
static var nameはあかんやろ
Avatar
nameが一般的すぎないかとはちょっと思ってましたが
Avatar
omochimetaru 4/26/2018 2:34 AM
でも型.nameだからまさにそうだと思うんだけどな
Avatar
テーブル型とCodable用の型わけるしかないねぇ
Avatar
omochimetaru 4/26/2018 2:35 AM
そうするとVaporのクエリ発行機能が死ぬね
Avatar
マジかよ
Avatar
omochimetaru 4/26/2018 2:35 AM
RonRのActiveRecordみたいなもんだから
Avatar
そういう仕組みかぁ
Avatar
omochimetaru 4/26/2018 2:35 AM
それ諦めちゃったらINSERTとかシコシコ書く状態になるだけ
Avatar
何とかできないかなァ
Avatar
omochimetaru 4/26/2018 2:36 AM
まあ一番簡単なのは
Avatar
static varをcomputeにしたらどうなる
Avatar
omochimetaru 4/26/2018 2:36 AM
テーブルのカラム名を name から name_ にするとかね
Avatar
もうやってたわ
Avatar
omochimetaru 4/26/2018 2:36 AM
static varをcomputeにすると、encode結果になぜかstaticの方が来る
2:36 AM
storedにするとinitができない。
Avatar
protocol extensionに追い出す
Avatar
omochimetaru 4/26/2018 2:37 AM
struct User: Codable { static var name: String { return "user" } var name_: String var name: String { return name_ } }
2:38 AM
こうやってテーブルのカラム名を name_ にすれば
2:38 AM
衝突回避できそう。
Avatar
敗北感高い
Avatar
omochimetaru 4/26/2018 2:38 AM
コンパイラが直るまでの処置やな
Avatar
static varをprotocol extensionに切り出して
2:38 AM
tablenameを定義するprotocolを作る
❗ 1
😀 1
Avatar
omochimetaru 4/26/2018 2:38 AM
UserProtocolを追加するってこと?
Avatar
そう
Avatar
omochimetaru 4/26/2018 2:39 AM
@swiftbot import Foundation protocol UserProtocol { static var name: String { get } } extension UserProtocol { static var name: String { return "user" } } struct User: UserProtocol, Codable { var name: String } let u = User(name: "hoge") let a = try! JSONEncoder().encode(u) print(String.init(data: a, encoding: .utf8))
🛠 1
Avatar
swiftbot BOT 4/26/2018 2:39 AM
Swift version 4.1 (swift-4.1-RELEASE)
2:39 AM
Optional("{\"name\":\"hoge\"}")
2:39 AM
/usercode/main.swift:17:7: warning: expression implicitly coerced from 'String?' to Any print(String.init(data: a, encoding: .utf8)) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usercode/main.swift:17:14: note: provide a default value to avoid this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ?? <#default value#> /usercode/main.swift:17:14: note: force-unwrap the value to avoid this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! /usercode/main.swift:17:14: note: explicitly cast to Any with 'as Any' to silence this warning print(String.init(data: a, encoding: .utf8)) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ as Any
Avatar
勝ち
Avatar
omochimetaru 4/26/2018 2:40 AM
Avatar
感謝してもいいのよ
Avatar
omochimetaru 4/26/2018 2:40 AM
hogeが出てるからencodeもあってるな
2:41 AM
このバグを回避するためにprotocolが一個増えるの・・・
Avatar
カラム変えるよりはマシ
Avatar
omochimetaru 4/26/2018 2:41 AM
微妙なラインだ
2:41 AM
カラムは別に見えないしマイグレーションで管理できるんや
Avatar
あとあと修正されて切り戻しを考えるとテーブルまで変更が及んでないほうが楽だと思いますね
Avatar
Optionalの待避と似たようなもんや
2:44 AM
ビジビリティ気になるならアンスコスタートにしとけばok
Avatar
omochimetaru 4/26/2018 2:46 AM
まあそうだね、UserProtocolとして何か適切に抽象化してるわけじゃないただの回避だから
Avatar
@swiftbot struct DBUser: Codable { static var name: String = "user" var name: String }
🛠 1
Avatar
swiftbot BOT 4/26/2018 2:46 AM
Swift version 4.1 (swift-4.1-RELEASE)
Avatar
omochimetaru 4/26/2018 2:46 AM
_User とかがよさそうだな。
2:47 AM
@swift-4.0.3 struct DBUser: Codable { static let name: String = "user" var name: String }
Avatar
exit status: 134 with stderr:swift: /home/buildnode/jenkins/workspace/oss-swift-4.0-package-linux-ubuntu-16_04/llvm/include/llvm/Support/Casting.h:236: typename cast_retty<X, Y *>::ret_type llvm::cast(Y *) [X = swift::MetatypeType, Y = swift::TypeBase]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed. #0 0x0000000003ae91b8 llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/usr/bin/swift+0x3ae91b8) #1 0x0000000003ae98f6 SignalHandler(int) (/usr/bin/swift+0x3ae98f6) #2 0x00007f6080f25390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #3 0x00007f607f664428 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35428) #4 0x00007f607f66602a abort (/lib/x86_64-linux-gnu/libc.so.6+0x3702a) #5 0x00007f607f65cbd7 (/lib/x86_64-linux-gnu/libc.so.6+0x2dbd7) #6 0x00007f607f65cc82 (/lib/x86_64-linux-gnu/libc.so.6+0x2dc82) #7 0x000000000054b72c (/usr/bin/swift+0x54b72c) #8 0x0000000000bf54a5 swift::Lowering::SILGenFunction::emitRValueForStorageLoad(swift::SILLocation, swift::Lowering::ManagedValue, swift::CanType, bool, swift::AbstractStorageDecl*, swift::Lowering::RValue, llvm::ArrayRef<swift::Substitution>, swift::AccessSemantics, swift::Type, swift::Lowering::SGFContext, bool) (/usr/bin/swift+0xbf54a5) #9 0x0000000000c08a02 (anonymous namespace)::NominalTypeMemberRefRValueEmitter::emit(swift::Lowering::SILGenFunction&) (/usr/bin/swift+0xc08a02) #10 0x0000000000c00bc6 swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) (/usr/bin/swift+0xc00bc6) #11 0x0000000000bf7a5c swift::Lowering::SILGenFunction::emitRValueAsSingleValue(swift::Expr*, swift::Lowering::SGFContext) (/usr/bin/swift+0xbf7a5c) #12 0x0000000000c7c137 (anonymous namespace)::ArgEmitter::emit(swift::Lowering::ArgumentSource&&, swift::Lowering::AbstractionPattern) (/usr/bin/swift+0xc7c137) #13 0x0000000000c7d6eb (anonymous namespace)::ArgEmitter::e
Avatar
omochimetaru 4/26/2018 2:47 AM
static let だとコンパイルできないけどstatic varはいけるのか。
Avatar
encodeはやっぱりこわれてますけどね
Avatar
とりあえず当面は @tarunon さんの方法で回避できそうです。 ありがとうございました。
👍 1
Avatar
@t.ae ↓これじゃダメ? @swiftbot import Foundation struct DBUser: Codable { static let name: String = "user" var name: String init(name: String) { self.name = name } private enum CodingKeys : CodingKey { case name } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let name = try container.decode(String.self, forKey: .name) self.init(name: name) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(name, forKey: .name) } } let u = DBUser(name: "hoge") let a = try! JSONEncoder().encode(u) print(String.init(data: a, encoding: .utf8)!)
🛠 1
😀 1
Avatar
swiftbot BOT 4/26/2018 3:27 AM
Swift version 4.1 (swift-4.1-RELEASE)
3:27 AM
{"name":"hoge"}
Avatar
omochimetaru 4/26/2018 3:28 AM
init(from Decoder)を手書きする方で避けるのか。
Avatar
うん、多分これって自動生成が壊れてるだけだから
Avatar
omochimetaru 4/26/2018 3:28 AM
たしかにいけるけどめんどくさいですね
Avatar
(そうじゃなかったら Codable にとどまらない問題があるだろうし)
Avatar
修正後も変更が不要という意味ではいいですね
Avatar
治ったら自動生成部分消すだけでいい。
Avatar
omochimetaru 4/26/2018 3:29 AM
あ〜
Avatar
まぁ別にprotocol切っても修正は不要か。
Avatar
omochimetaru 4/26/2018 3:29 AM
いや
3:29 AM
protocol切る場合はstatic varの実装をコピペして戻す必要はある
3:29 AM
消すだけよりは手間がかかる (edited)
3:30 AM
でもfromDecoderとencodeは徹底して書かないようにしてるからCodingKeysからやるのめんどそうだなと思った
3:30 AM
でも変な事はしてないという意味では良いですね
3:30 AM
手書きしてるだけで。
Avatar
同じ自動生成でも↓はできた。興味深い。 @swiftbot import Foundation struct DBUser: Equatable { static let name: String = "user" var name: String } let u1 = DBUser(name: "hoge") let u2 = DBUser(name: "fuga") print(u1 == u2) (edited)
🛠 2
Avatar
swiftbot BOT 4/26/2018 3:32 AM
Swift version 4.1 (swift-4.1-RELEASE) (edited)
3:32 AM
false (edited)
Avatar
omochimetaru 4/26/2018 3:33 AM
それってuserとhogeのどっちで見てるんでしょう?
Avatar
static のほうで比較してたりして
Avatar
omochimetaru 4/26/2018 3:33 AM
u == u だとわからなくないですか?
Avatar
swiftbot BOT 4/26/2018 3:33 AM
swift-DEVELOPMENT-SNAPSHOT-2018-04-18-a Swift version 4.2-dev (LLVM d14a2b25f2, Clang da1edea3f7, Swift ac061632b2)
3:33 AM
true
3:33 AM
swift-DEVELOPMENT-SNAPSHOT-2018-04-18-a Swift version 4.2-dev (LLVM d14a2b25f2, Clang da1edea3f7, Swift ac061632b2)
3:33 AM
false
Avatar
修正してみた。
Avatar
omochimetaru 4/26/2018 3:33 AM
falseになったからちゃんと動いてるか。
Avatar
CodableEquatable の自動生成周りのコード見比べてみたらおもしろいことがわかりそう。
Avatar
Equatableの場合は全件比較の可能性もないですかね? Codableの場合は名前衝突してstaticのほうだけのこってしまってるとか
3:35 AM
そこらへんはあまり抽象化されてないから
3:35 AM
フィールドのイテレーションロジックは
3:35 AM
生成器ごとに手書きされてるよ
3:36 AM
型のDeclContextからメンバを拾ってイテレートするところで
3:37 AM
static fieldかどうかのチェックを忘れてる箇所があると予想
3:47 AM
こっちか。
3:47 AM
class VarDeclに .isStatic() がある
Avatar
対応してるのかわからないけど、↓だと stored property だけとってる? https://github.com/apple/swift/blob/master/lib/Sema/DerivedConformanceEquatableHashable.cpp#L512
swift - The Swift Programming Language
Avatar
omochimetaru 4/26/2018 3:50 AM
auto storedProperties = structDecl->getStoredProperties(/*skipInaccessible=*/true);
3:50 AM
おお。
3:51 AM
ああそうか
3:51 AM
CodableはCodingKeysをベースに回してるから
3:51 AM
ちょっとスタイルが違うのか。
3:52 AM
getStoredPropertiesの中身を見れば、何に気をつければいいかわかりそうだ。
Avatar
Enumを生成勝手に出来ないようにする方法って無いですよね
7:02 AM
structはinitをpublicにしなければ勝手に生成出来ないけど
Avatar
omochimetaru 4/26/2018 7:03 AM
無さそう
Avatar
フーム
7:10 AM
enumをwrapするstructを作ってそれのinitを隠蔽して外側のstructのみが証明されたものという扱いにしないといけないか
7:11 AM
availablityに修飾子つけれるようになればcase自体をdeprecatedとか出来るのかしら
Avatar
enum A { case hoge(String) } protocol AP {} extension AP where Self == A { static var hoge: (String) -> Self { fatalError() } } extension A: AP {} A.hoge("aa")
7:16 AM
生成できなくなった
Avatar
omochimetaru 4/26/2018 7:16 AM
同名static funcでshadowだと・・・
Avatar
これenumの中に定義しようとするとredeclarationで弾かれるんですけど、protocol exだとできるんですよね
Avatar
norio_nomura 4/26/2018 7:19 AM
@swift-4.1.3 enum A { case hoge(String) } protocol AP {} extension AP where Self == A { static var hoge: (String) -> Self { fatalError() } } extension A: AP {} A.hoge("aa")
Avatar
exit status: 1 with stderr:main.swift:14:1: error: ambiguous use of 'hoge' A.hoge("aa") ^ main.swift:2:10: note: found this candidate case hoge(String) ^ main.swift:7:16: note: found this candidate static var hoge: (String) -> Self { ^
Avatar
staticのはちょうどこれが直してるところかな https://github.com/apple/swift/pull/16143
…n static/instance properties. Previously, we just took the first match so: We would try to emit a metatype lookup of the property but had prepared an instance lookup. Could get the wrong type if ...
1:15 AM
4.2で直りそう
👀 1
Avatar
class Class { static lazy var value: Int = { preconditionFailure() }() } とするとalready-lazyと怒られたので
10:11 AM
class Class { static var value: Int = { preconditionFailure() }() } Class.value = 1 こんな感じで定義したのですが、どうも代入前にpreconditionFailureが呼ばれているようなのですがこれはどうしてなのでしょう…?
10:11 AM
valueのsetterで代入前に初期化しているような挙動になってしまう
Avatar
クロージャで囲ってるのはNeverがBottom Typeじゃないからか。。。
Avatar
なるほど
10:14 AM
Swiftのグローバル・Static変数のlazy化は
10:15 AM
あくまで最適化の範疇で勝手にやっていることであって
10:15 AM
メンタルモデルとしては忘れて良いもので
10:15 AM
という意味では、 Class.value = 初期値
10:15 AM
実行されていることになるんじゃないですかね?
10:16 AM
だから、 Class.value への最初のアクセスが発生した時点で、 初期値の代入処理が実行、 (この場合 preconditionfailure) その後で 実際のアクセス(この場合1の代入 )
10:17 AM
lazyをつけた場合は、これは、readするときに実行されるものって決まってるので、若干意味が違うと思う
10:17 AM
意味が違うから書き分ける事に合理性があるのに、already lazyってエラーになっていることがおかしいように思う。
Avatar
コンパイラエラーのalready lazyは所謂@lazyとは意味合いが違うということですね、なるほど
10:21 AM
ちょっとこの辺り気になって上記のvaluexxxxxxxxxxとリネームした状態でSILを吐いてみたのですが、 // static Class.xxxxxxxxxx.setter sil hidden [transparent] @_T04main5ClassC10xxxxxxxxxxSivsZ : $@convention(method) (Int, @thick Class.Type) -> () { // %0 // users: %8, %2 // %1 // user: %3 bb0(%0 : $Int, %1 : $@thick Class.Type): debug_value %0 : $Int, let, name "value", argno 1 // id: %2 debug_value %1 : $@thick Class.Type, let, name "self", argno 2 // id: %3 // function_ref Class.xxxxxxxxxx.unsafeMutableAddressor %4 = function_ref @_T04main5ClassC10xxxxxxxxxxSivau : $@convention(thin) () -> Builtin.RawPointer // user: %5 %5 = apply %4() : $@convention(thin) () -> Builtin.RawPointer // user: %6 %6 = pointer_to_address %5 : $Builtin.RawPointer to [strict] $*Int // user: %7 %7 = begin_access [modify] [dynamic] %6 : $*Int // users: %9, %8 assign %0 to %7 : $*Int // id: %8 end_access %7 : $*Int // id: %9 %10 = tuple () // user: %11 return %10 : $() // id: %11 } // end sil function '_T04main5ClassC10xxxxxxxxxxSivsZ' %5 = apply %4() : $@convention(thin) () -> Builtin.RawPointer // user: %6 ここで代入前に初期化(preconditionFailure)されてしまっているということなのでしょうか…? SIL全然読めないのでついていけなくなったらすいません
Avatar
public func undefined<T>(file: StaticString = #file, line: UInt = #line) -> T { fatalError("undefined", file: file, line: line) } class Class { class StaticStorage { lazy var value: Int = undefined() static let shared = StaticStorage() } static var value: Int { get { return StaticStorage.shared.value } set { StaticStorage.shared.value = newValue } } } // 代入前にreadするとクラッシュ // print(Class.value) Class.value = 3 print(Class.value) (edited)
10:22 AM
とりあえずやりたいことはできた↑
10:27 AM
ですね
10:27 AM
こっちでもSIL吐いて読んでみたんですけど
10:30 AM
セッター _T01a5ClassC5valueSivsZ ストレージを取得する関数 _T01a5ClassC5valueSivau この中に、 "once" ってbuildinコマンドの呼び出しがある そのonceに渡されている関数。 globalinit_33_EFF83A1F47B777EA672D48C97C71346F_func0 その中で呼ばれてる関数 _T01a5ClassC5valueSivpZfiSiycfU_ この中に、preconditionFailureの呼び出しがある。 _T0s19preconditionFailures5NeverOSSyXK_s12StaticStringV4fileSu4linetFfA_ (edited)
10:32 AM
マングリングの Sivau で検索してみたら、 lazy とか global とか書いてあるのがいろいろでてきた。 https://github.com/apple/swift/search?utf8=✓&q=Sivau&type=
Avatar
ありがとうございます、追えました。確かにpreconditionFailureがbegin_access前に呼ばれていました。(Sivauがちょっと何ものなのかまだ分かってないですが…)
11:11 AM
%4 = function_ref @_T04main5ClassC10xxxxxxxxxxSivau : $@convention(thin) () -> Builtin.RawPointer // user: %5 %5 = apply %4() : $@convention(thin) () -> Builtin.RawPointer // user: %6 %6 = pointer_to_address %5 : $Builtin.RawPointer to [strict] $*Int // user: %7 %7 = begin_access [modify] [dynamic] %6 : $*Int // users: %9, %8 代入先のアドレスを取得するために初期化しているような感じなんですね
11:17 AM
Sivauはここ読めば解読できるかも。
Avatar
i Int v variable a mutable addressor u unsafe addressor っぽい。
11:28 AM
Sがわからーん
11:31 AM
any-generic-type ::= 'S' KNOWN-TYPE-KIND
11:31 AM
このSだろうか?
11:32 AM
でもジェネリックって書いてあるし関係なさそう
Avatar
any-generic-type ::= 'S' KNOWN-TYPE-KIND // known nominal type substitution KNOWN-TYPE-KIND ::= 'i' // Swift.Int Sは単なる組み込み型の接頭文字だと思われます。
12:04 PM
AST でいうところの AnyGenericType は 全ての NominalType の親なので、非常に範囲広いです。
Avatar
なるほどなるほど
Avatar
ジェネリクスの方のgenericじゃなくてそのままの意味か
Avatar
これそもそも、setter呼んでるだけなのに値代入されるのなぞですよね。 意図した動作なのか、意図してないけど妥協されている動作なのか、どちらでしょう。未定義なのかどうかだけでも気になる。
Avatar
omochimetaru 4/28/2018 5:45 AM
文書は見かけてないけど、普通のローカル変数と対比して考えれば、 (1)の代入が(2)より先に発生するのは自然だと思います。 var a: Int = { preconditionFailure() }() // (1) a = 3 // (2)
Avatar
lazyなインスタンス変数なら、クロージャの中身は呼ばずにsetterを呼び出せるので、仕様上lazyであるstatic変数だと出来ない仕様になっているのは謎だなぁ、と思いまして… ローカル変数はlazyじゃないですしね… class Hoge { lazy var a: Int = { preconditionFailure() }() } let h = Hoge() h.a = 1 print(h.a) (edited)
Avatar
意味が違うから書き分ける事に合理性があるのに、already lazyってエラーになっていることがおかしいように思う。
これに同意で、とりあえず bugs.swift.org にイシュー投げて反応見るっていうのが良いと思いますよ。
Avatar
@malt03 はい、なので「static変数がlazy化される」ときのlazyと、構文として lazy を書いた時のlazyの概念は別物だと思います。
10:43 AM
別物なのに、同時指定が怒られるコンパイラがおかしい、と考えるか、 同時指定ができない同じものなのに、挙動が違うのがおかしい、と考えるかは、2択ありますけど (edited)
10:45 AM
static変数のlazy化は、見た目には普通の初期値代入なので、 初期済み変数への代入よりも事前に、初期値の構築の際に生じる副作用が生じていないと、おかしいと思うので、 現在の振る舞いが正しいと思います。
Avatar
初期値の構築の際に生じる副作用が生じていないと、おかしいと思う
ただしいつ起きるかは undefined という。
Avatar
構文としてのlazyは「最初のread時に値が構築される」で、 static変数のlazy化は「初期値の代入がギリギリまで遅延される」かなと。
Avatar
undefined というよりは unpredictable か。 (edited)
Avatar
似たような、スタティックスコープの初期化順の問題は他の言語にもあって、
10:50 AM
C++だとmain突入前に全て実行、main終了後に全てdestruct Javaだと、クラスファイルロード時にそのクラスファイルに関して全て実行 だった気がする。
10:51 AM
Swiftの場合その変数ごとになってるっぽいのでそのどちらよりも遅延しえて、たとえロードされたパッケージに定義されていたとしても、アクセスされない変数がアプリケーション終了時まで一度も初期化されない、可能性がある気がする。 例のごとく規格とかは厳密に決まって無さそうだけど。 (edited)
Avatar
bugs書こうと思ったけどこのマシンがまだローシエラだ・・・
11:16 AM
This is currently by design, but it might be worth changing the design.
となると Evolution 案件ですね。
(edited)
Avatar
https://github.com/apple/swift/pull/16376 Extension で Codable の諸々自動生成が効かない問題が解決されそうです。
This works for Equatable, Hashable, Encodable, Decodable (and thus Codable), and CaseIterable. For instance, struct Foo<T> { var x: T } extension Foo: Equatable where T: Equatable {} Fix...
😀 2
Avatar
https://bugs.swift.org/browse/SR-6803 同一ファイル内に限り、ですかね。 (edited)
Avatar
この前 @Taketo Sano さんが困ってた自作型の Conditional Conformance & Codable 自動生成はできるようになりそうですね。
Avatar
init(from decoder: Decoder)private var に対する assign がエラーになりそうな予感。
2:52 AM
https://github.com/apple/swift/pull/16376/files#diff-01a6eb231899c107eafd479a7ffe09f7R376 シンプルな enum に対する Equatable,Hashable だけは別ファイルでもいけるっぽいですね。 (edited)
This works for Equatable, Hashable, Encodable, Decodable (and thus Codable), and CaseIterable. For instance, struct Foo<T> { var x: T } extension Foo: Equatable where T: Equatable {} Fix...
2:57 AM
ってその辺は元々暗黙でconformしているやつか。
Avatar
Taketo Sano 5/7/2018 3:14 AM
おぉ…!
Avatar
Swift の Boolenum じゃなく struct なのって何か理由があるんでしたっけ?↓で良さそうなのに。 enum Bool { case true case false }
Avatar
omochimetaru 5/7/2018 4:27 AM
昔はcaseは大文字だったから enum Bool { case True, case False } になるのかな
Avatar
にしても、 ExpressibleByBooleanLiteral (昔の BooleanLiteralConvertible )で true, false からマッピングすればいいだけだったはずだからなぁ。
Avatar
omochimetaru 5/7/2018 4:30 AM
enumになってたほうが
4:30 AM
フラグの組み合わせをswitchで網羅できたりして便利?
4:30 AM
なってない理由は無くて誰も気がついてないような気がする(論点として見たことがない
Avatar
switch網羅はいまもできないですっけ?
Avatar
omochimetaru 5/7/2018 4:32 AM
できるんだっけ、なんでできるんだ?
Avatar
https://github.com/apple/swift/blob/master/docs/archive/LangRefNew.rst#bool-true-false 議論されたことが無いということはないようです。
swift - The Swift Programming Language
Avatar
omochimetaru 5/7/2018 4:32 AM
Bool, true, false // Bool is a simple enum. enum Bool { true, false } // Allow true and false to be used unqualified. var true = Bool.true var false = Bool.false
4:32 AM
Avatar
@swiftbot let a = false let b = true switch (a, b) { case (true, true): break case (true, false): break case (false, true): break case (false, false): break }
🛠 1
Avatar
swiftbot BOT 5/7/2018 4:33 AM
Author icon
t.ae
let a = false let b = true switch (a, b) { case (true, true): break case (true, false): break case (false, true): break case (false, false): break }
Version:
swift-4.1.1-RELEASE
Output:
Error:
Avatar
omochimetaru 5/7/2018 4:33 AM
なんかbotがオシャレになってるw (edited)
4:34 AM
@swiftbot let a = false let b = true switch (a, b) { case (true, true): break case (true, false): break case (false, true): break }
🛠 1
Avatar
swiftbot BOT 5/7/2018 4:34 AM
Author icon
omochimetaru
let a = false let b = true switch (a, b) { case (true, true): break case (true, false): break case (false, true): break }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:4:1: error: switch must be exhaustive switch (a, b) { ^ /usercode/main.swift:4:1: note: add missing case: '(false, false)' switch (a, b) { ^
Avatar
omochimetaru 5/7/2018 4:34 AM
網羅性検査はされるのか。
4:35 AM
enumだったら、 case (.true, .true):
Avatar
特別扱いなんじゃない?
Avatar
Bool は特別扱いですね。
Avatar
omochimetaru 5/7/2018 4:37 AM
うーんまあいいのか、Intも特別扱いがそのうちされたら嬉しいし。
Avatar
swift - The Swift Programming Language
Avatar
omochimetaru 5/7/2018 4:38 AM
でたonenof
4:38 AM
しかも最初はoneofだったのか!
Avatar
なんで enum じゃなかったんだろう??
Avatar
omochimetaru 5/7/2018 4:38 AM
ADTを意識してた?
Avatar
enum とは別物?
Avatar
omochimetaru 5/7/2018 4:39 AM
ってかこのconstructor() { } ってのkotlinっぽいな。
Avatar
Rust にインスパイアされたって話からすると enum が自然そうなのに。
Avatar
omochimetaru 5/7/2018 4:39 AM
func __equal__(rhs: Bool) -> Bool { pythonみたいなやつある・・・ (edited)
Avatar
この後このmassiveなコミットでガッと書き換えられたので、経緯は追えないですね。 https://github.com/apple/swift/commit/fad874708e05cff56aec5587a4b0f49cdadc6d11
👀 1
Avatar
omochimetaru 5/9/2018 1:06 AM
This works for Equatable, Hashable, Encodable, Decodable (and thus Codable), and CaseIterable. For instance, struct Foo<T> { var x: T } extension Foo: Equatable where T: Equatable {} Fix...
1:07 AM
Equatableの自動実装が条件付きエクステンションでもできるようになった
1:08 AM
最近Codableでこれを踏んだような気がする 本体に付けないとダメなのかーって
Avatar
The core team has approved an amendment to SE-0185 "Synthesizing Equatable and Hashable conformance to allow synthesis of conformances declared on same-file extensions. For example, the following is now well-formed, and will synthesize a conditio...
10:56 AM
朝のやつ、仕様変更したぜってアナウンス来てた。
10:57 AM
プロポザルレビューのタグがついてるけど
Avatar
Equatableの自動実装、エクステンションだと再帰的になってるとできないの惜しい (edited)
1:02 PM
@swiftbot --version=latest indirect enum A { case a(A) } extension A: Equatable {} (edited)
🛠 1
Avatar
swiftbot BOT 5/11/2018 1:02 PM
(edited)
Author icon
kateinoigakukun
indirect enum A { case a(A) } extension A: Equatable {}
Version:
swift-4.2-DEVELOPMENT-SNAPSHOT-2018-05-08-a
Output:
Error:
/usercode/main.swift:5:1: error: implementation of 'Equatable' cannot be automatically synthesized in an extension extension A: Equatable {} ^
Avatar
@swiftbot --version=latest indirect enum A: Equatable { case a(A) } (edited)
🛠 1
Avatar
swiftbot BOT 5/11/2018 1:03 PM
(edited)
Author icon
kateinoigakukun
indirect enum A: Equatable { case a(A) }
Version:
swift-4.2-DEVELOPMENT-SNAPSHOT-2018-05-08-a
Output:
Error:
Avatar
これはできるのか
Avatar
ところでその A 無限再帰してインスタンス作れなくないですか?
Avatar
あー、確かにそうですね
2:15 PM
@swiftbot —version=latest enum A { case a([A]) } extension A: Equatable {} (edited)
🛠 1
Avatar
swiftbot BOT 5/11/2018 2:15 PM
(edited)
Author icon
kateinoigakukun
enum A { case a([A]) } extension A: Equatable {}
Version:
swift-4.2-DEVELOPMENT-SNAPSHOT-2018-05-08-a
Output:
Error:
/usercode/main.swift:5:1: error: implementation of 'Equatable' cannot be automatically synthesized in an extension extension A: Equatable {} ^
Avatar
@swiftbot —version=latest enum A: Equatable { case a([A]) } (edited)
🛠 1
Avatar
swiftbot BOT 5/11/2018 2:16 PM
(edited)
Author icon
kateinoigakukun
enum A: Equatable { case a([A]) }
Version:
swift-4.2-DEVELOPMENT-SNAPSHOT-2018-05-08-a
Output:
Error:
Avatar
a([A]) だと indirect 要らなさそうですね🙂
💯 1
Avatar
AがEquatable自動実装できるかどうかを調べる中で、aのAがEquatableか調べる必要があって〜、、、って感じで無限に続きそうですけど、これどうやって通してるんですかね (edited)
Avatar
A : Equatable だから [A] : Equatablecase a([A])Equatable で、すべての caseEquatable なので A : Equatable を満たすので自動生成、ですかね?
Avatar
最初のA : Equatableだから〜の部分は仮定ですか? (edited)
Avatar
はい。その仮定が正しいかを検証しているからその仮定の元で仮定が真であることが示されるみたいな?
Avatar
数学的帰納法っぽい感じかな?
Avatar
実際にコンパイラがどのような手順でやってるかは知らないので想像ですが・・・
Avatar
ちょっと興味湧いてきたので読んでみます
👍 1
1:09 AM
文字列展開をビルダーパターンにコンパイルする案 バッファサイズ予測を付けて、個別のString結合するより速くなる
Avatar
すでにそうなってるもんだと勝手に思ってました 🙄
Avatar
omochimetaru 5/15/2018 1:13 AM
気持ちはわかりますwJavaとかそうですしね。
Avatar
ということは、今は単純に + で連結するのと同じ感じで動いているんですかね。
1:15 AM
文字列型に変換するところは別にして (edited)
🤔 1
Avatar
omochimetaru 5/15/2018 1:18 AM
まんまですね
Avatar
omochimetaru 5/15/2018 8:18 AM
@swiftbot extension String : Error {} func hoge() { do { throw "aaa" } catch { print("catch error: \(error)") } } hoge()
🛠 1
Avatar
swiftbot BOT 5/15/2018 8:18 AM
Author icon
omochimetaru
extension String : Error {} func hoge() { do { throw "aaa" } catch { print("catch error: \(error)") } } hoge()
Version:
swift-4.1.1-RELEASE
Output:
catch error: aaa
Error:
Avatar
omochimetaru 5/15/2018 8:18 AM
catchって単体で書くと error って変数にエラーが入るの・・・・・・
Avatar
@swiftbot struct MyError: Error {} do { throw MyError() } catch is MyError { print("my error: \(error)") } catch { print("\(error)") }
🛠 1
Avatar
swiftbot BOT 5/15/2018 8:21 AM
Author icon
t.ae
struct MyError: Error {} do { throw MyError() } catch is MyError { print("my error: \(error)") } catch { print("\(error)") }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:5:24: error: use of unresolved identifier 'error' print("my error: \(error)") ^~~~~ Swift.Error:1:17: note: did you mean 'Error'? public protocol Error { ^ Swift.Mirror:1:15: note: did you mean 'Mirror'? public struct Mirror { ^
Avatar
こっちにもいれてほしい
Avatar
ごもっとも。
Avatar
Swift 4.2 で導入される標準の Random って seed を与えられない? https://github.com/apple/swift/blob/master/stdlib/public/core/Random.swift#L133-L157
swift - The Swift Programming Language
Avatar
omochimetaru 5/18/2018 3:47 AM
RandomはRandomGeneratorってprotocolを満たす簡単実装のひとつにすぎないから
3:48 AM
端折られてても違和感は無いですね
3:48 AM
安全な乱数の場合シードできないので。
Avatar
うん、そうなんだけど、標準で seed 与えられるものが提供された方が便利そう
3:48 AM
テストとかで再現させるのに、いちいち実装が必要だと大変
Avatar
omochimetaru 5/18/2018 3:49 AM
えっと、ランダムジェネレータって大きく2つあって
3:49 AM
CSPRNGなやつと、高速で再現性のあるやつ
3:49 AM
シードを与えられるのは後者で、セキュリティ目的で望ましいのは前者
3:49 AM
それで、「デフォルトのRandom」をどっちにするかって議論があって
3:50 AM
なんかいろいろ話されてるんだけど、 名前ちゃんとつけようぜ、っていう別の提案議論も並行して今やってるので
3:50 AM
ちょっとどうなるかわかんない
Avatar
なるほど。いずれにしても両方ほしい気が。
Avatar
omochimetaru 5/18/2018 3:50 AM
2つの両方の保守的な性質を満たすもの(安全でもないし再現性も取れない)
3:50 AM
にするってパターンもありえるかも?
3:51 AM
いずれかの性質が欲しい時は明示的にそのようなジェネレータを使う。
3:51 AM
はい、RndomNumberGeneratorはプロトコルだから (edited)
3:51 AM
具体的な型としてそれぞれ提供されるはず。
3:52 AM
public struct Random : RandomNumberGenerator {
3:52 AM
The accepted proposal to add Random API to the standard library defines a single random source in the standard library. Users can create their own random sources by writing types that conform to the RandomNumberGenerator protocol. For convenience...
3:52 AM
このスレッド。
👍 1
3:57 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
3:57 AM
The aspiration is that this RNG should be cryptographically secure, provide reasonable performance, and should be thread safe.
3:58 AM
cryptographically secureが should be って無意味に思う・・・
3:59 AM
must be じゃないなら、「稀にsecureでない」セキュリティバグを産みうるだけ
Avatar
RC4がセキュアでなくなったようにセキュアの基準が変わる事があるので、must beは難しいのだと思います。
Avatar
またその次の文にもあるように、そもそもセキュアな発生器を提供出来ないプラットホームに移植する可能性も考えて、その制限をつけられないという判断。
Avatar
omochimetaru 5/18/2018 4:37 AM
RandomNumberGeneratorという基本のプロトコルがmust beにできないという点は同意で、 should be といわずにばっさり not secure って定義しちゃうほうが事故がないと思いまして。
Avatar
プロトコルじゃなくて、そのデフォルト実装である Random の話ですよね? 定義が中途半端なのは同意します。
Avatar
omochimetaru 5/18/2018 5:30 AM
いえ、さっきの should be の文は Proposed Solution の Random Number Generator について述べられたセンテンスで、 Randomについてはそれのデフォルト実装だよ、としか書いてないような。
Avatar
Random Number Generator の 最初の文が "To kick this off, the standard library will provide a default RNG" なので、このセクション自体がデフォルト実装に関する話だという理解です。
Avatar
omochimetaru 5/18/2018 8:32 AM
なるほど
Avatar
lldbについて質問です。Xcode上でswiftcのc++コードをデバッグしたいんですが、pコマンドを実行すると下記のエラーが出ます。Xcodeで開いているswiftcは--release-debuginfo -xでビルドしていて、実行時には-gオプションを付けて実行しています。swiftcを--debugでビルドすればlldbでデバッグできますか? (lldb) p OutputFile error: Couldn't materialize: couldn't get the value of variable OutputFile: no location, value may have been optimized out error: errored out in DoExecute, couldn't PrepareToExecuteJITExpression
Avatar
はい、 RelWithDebInfo はデバッグ情報は保持されますが (edited)
10:51 AM
最適化自体は実行されてしまうため、しっかりデバッグしたいときは、デバッグビルドのほうがいいです。ただ、全部をデバッグビルドすると非常に遅いので、
10:53 AM
--release-debuginfo --debug-swift でstdlibや、llvmやclangなどの依存ライブラリは最適化しつつ、 swift/swiftc だけデバッグビルドに出来るので、そっちのほうがいいかもしれません。 (edited)
10:55 AM
この場合、ビルドディレクトリは build/Ninja-RelWithDebInfoAssert+swift-DebugAssert になります。
Avatar
そうか、--debug-swiftがあるのか。ありがとうございます、さっそく試してみます!
Avatar
omochimetaru 5/21/2018 6:18 AM
なるほど、元の質問の答え自体は、デバッグはできる状態だけどリリースビルドではあるからデバッグできないシンボルが出る事はあるよ、って話か。
Avatar
--debug-swiftでビルドしたXcodeプロジェクトならlldbでデバッグ出来るようになりました!これは革命だ!ありがとうございました。
Avatar
当方Swift初心者なのですが、 NSRegularExpression にextensionでfailable initializer生やしたいだけでハマったのですが、これはできない? protocol Foo { init?(string: String) } extension NSRegularExpression: Foo { // ??? }
7:15 AM
@objc のconstructorムズすぎで未だに雰囲気
Avatar
init?(string: String)を書けば行けるんじゃないですか?
7:18 AM
あーrequiredとかで怒られるやつですか
Avatar
omochimetaru 5/23/2018 7:23 AM
ObjC関係ない気がする。 protocol Foo { init(string: String) } class Cat { init() {} } extension Cat : Foo { convenience init(string: String) { self.init() } } ↑できない。
7:24 AM
protocolで制約されるinitは、サブクラスにも生えている必要があるから
7:24 AM
required initとして実装する必要があるけど
7:25 AM
extensionにはrequired initをかけないので(なんでだっけ)
7:25 AM
final class + extension { convenience init } の形でしか通せない? (edited)
7:26 AM
(final classならサブクラスは無いからそのクラスでinit呼べる事が保証できる)
Avatar
protocolで制約されるinitは、サブクラスにも生えている必要があるから
required initとして実装する必要があるけど
7:28 AM
なるほど
Avatar
omochimetaru 5/23/2018 7:29 AM
間違ってる気もする。init自体はサブクラスにも暗黙に存在してるっけ?
Avatar
NSObjectProtocol 継承してそうだから (edited)
7:29 AM
init自体は存在してるはず
7:30 AM
単に NSObject
Avatar
omochimetaru 5/23/2018 7:31 AM
一般の話しでした。 class Animal { init(aaa: Int) {} } class Cat : Animal { init(bbb: Float) { super.init(aaa: 0) } } Cat.init(aaa: 0) // コンパイルエラー
7:31 AM
やっぱり、ただのinitは継承先で消えますね。
Avatar
なるほどなー
Avatar
omochimetaru 5/23/2018 7:32 AM
class Animal { // requiredだと子にも定義が必要になる required init(aaa: Int) {} } class Cat : Animal { // これが必要 required init(aaa: Int) { super.init(aaa: 0) } init(bbb: Float) { super.init(aaa: 0) } } Cat.init(aaa: 0) // 当然OK
Avatar
ですね
Avatar
omochimetaru 5/23/2018 7:33 AM
なのでそこから考えると、 protocol Foo は Animal が満たせば暗黙に Cat も満たされるわけだから、 Fooのinitを実装する側はrequiredでなければならない。 (edited)
Avatar
明示的にrequiredで再実装したら行けるか見てみるか
Avatar
omochimetaru 5/23/2018 7:33 AM
それをやろうとすると
7:33 AM
extensionではrequired initはかけませ〜ん ってエラーが出た。
Avatar
うーん
Avatar
omochimetaru 5/23/2018 7:34 AM
サブクラスは外のモジュールで実装される事もあるから
7:34 AM
extensionで追加したinitがサブクラス側で考慮されない事はありえるから
7:34 AM
エラーになる理屈はわかるけどシンプルにやりたいことができない感じでモヤモヤしますな
Avatar
NSRegularExpression を継承したクラスでラップしたらいけた
Avatar
omochimetaru 5/23/2018 7:36 AM
僕はどっちにしろ使いにくいのでRegexはラップしちゃってます。
Avatar
protocol Foo { init?(string: String) } class SubRegExp: NSRegularExpression { override init(pattern: String, options: NSRegularExpression.Options = []) throws { try super.init(pattern: pattern, options: options) } convenience init?(string: String) { try? self.init(pattern: string, options: .caseInsensitive) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } (edited)
7:37 AM
できた
7:37 AM
まじかよ
Avatar
omochimetaru 5/23/2018 7:38 AM
それはrequired initがextensionじゃなくてclass本体に書いたからOKですね
7:38 AM
required initだから SubRegExpのさらなる子どもたちは全員そのinitを持つからOK。
Avatar
あ、Fooないじゃん
7:38 AM
protocol Foo { init?(string: String) } class SubRegExp: NSRegularExpression, Foo { override init(pattern: String, options: NSRegularExpression.Options = []) throws { try super.init(pattern: pattern, options: options) } convenience required init?(string: String) { try? self.init(pattern: string, options: .caseInsensitive) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
7:38 AM
こうか
7:38 AM
なるほど〜
7:39 AM
うーん、こういうものなのか。勉強になりました
Avatar
omochimetaru 5/23/2018 7:39 AM
ああそうか、convenience requiredになるのか。他のinitを呼びたいから。
7:40 AM
@objc protocol Foo { optional init(string: String) } これでいけないかと思ったけど
error: iOSGround.playground:4:5: error: 'optional' cannot be applied to an initializer
optional init(string: String)
Avatar
最近ライブラリ作って、 Foo に相当するプロトコルを提供してるんだけど、staticメソッドでやるか、initializerでやるかなやんで、initializerの方が良いか、と思ってこういうインターフェイスにしたら使えない場合が判明して困った
Avatar
omochimetaru 5/23/2018 7:42 AM
ああなるほど。
Avatar
protocol Foo { static func decode(string: String) -> Self? } (edited)
7:43 AM
おとなしくこれにしておいた方が良い
Avatar
omochimetaru 5/23/2018 7:43 AM
static funcだと何が変わるんだろ 子にも生えるからか?
7:44 AM
required initはextensionにかけないのにstatic funcはextensionに書けるのも矛盾を感じる
Avatar
うーん、でもやはりこれでも無理そう
Avatar
omochimetaru 5/23/2018 7:48 AM
それはそれで Self 周りの取扱でややこしくなりがち
Avatar
protocol Bar { static func decode(string: String) -> Self? } extension NSRegularExpression: Bar { static func decode(string: String) -> NSRegularExpression? { return try? NSRegularExpression(pattern: string, options: .caseInsensitive) } } error: method 'decode(string:)' in non-final class 'NSRegularExpression' must return Self to conform to protocol 'Bar' static func decode(string: String) -> NSRegularExpression? {
7:53 AM
めっちゃシンプルだから行けそうに見えてダメだにゃんだな〜
Avatar
omochimetaru 5/23/2018 7:54 AM
そうすると class SubRegex : NSRegularExpression { } があった場合に
7:54 AM
SubRegexには static func decode () -> SubRegex が生えてないといけないのに
Avatar
そういう事なんでしょうね
Avatar
omochimetaru 5/23/2018 7:55 AM
実際にはNSRegularExpressionから継承された NSRegularExpression { static func decode() -> NSRegularExpression } になってて駄目なんですよね
Avatar
意外と当然できるでしょ、と思ってた挙動が書いてみるとできないと言うことが判明した・・・・・・
7:55 AM
まだまだ知らないことばかりだ
Avatar
omochimetaru 5/23/2018 7:55 AM
実装側の static func decode(string: String) -> NSRegularExpression? -> Self にすると定義できるんだけど
Avatar
理屈を聞けば納得
Avatar
omochimetaru 5/23/2018 7:56 AM
Self 型の式をreturnするのが難しい。self.init() などになる。 (selfはメタクラス)
7:57 AM
HimotokiとかArgoとかの同種のライブラリは
7:57 AM
decodeの返り値をSelfじゃなくてassociatedtype Decodedにすることで
7:57 AM
継承先であっても親の型としてデコードさせるように制限することで成り立たせてるけど
7:57 AM
それはそれで面倒なwhere句がそこらじゅうに必要になるのであった
Avatar
norio_nomura 5/23/2018 7:59 AM
@swift-4.1.3 import Foundation protocol Bar { static func decode(string: String) -> Self? } extension NSRegularExpression: Bar { static func decode(string: String) -> Self? { return try? .init(pattern: string, options: .caseInsensitive) } } let bar = NSRegularExpression.decode(string: ".*") print(bar! is Bar) (edited)
Avatar
truestderr:<stdin>:14:12: warning: 'is' test is always true print(bar! is Bar) ^ (edited)
Avatar
いけてそう。なるほどなあ
8:17 AM
ありがとうございました 👏
🙂 1
Avatar
↓の message のデフォルト引数が "" じゃなくて String() になってるのってなんででしょう? ExpressibleByStringLiteral 経由だと無駄な処理が走るから? public func fatalError( _ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line ) -> Never { https://github.com/apple/swift/blob/master/stdlib/public/core/Assert.swift#L193
swift - The Swift Programming Language
Avatar
とりあえず -O で同等の SIL が出力されることは確認しました。理由分からず。
🤔 1
6:30 AM
あ、うそ SIL 違いました
6:33 AM
= String() // default argument 0 of DEFAULT_CONST(x:) sil non_abi @$S4test13DEFAULT_CONST1xySSyXK_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> @owned String { bb0: // function_ref implicit closure #1 in default argument 0 of DEFAULT_CONST(x:) %0 = function_ref @$S4test13DEFAULT_CONST1xySSyXK_tFfA_SSyXAfu_ : $@convention(thin) () -> @owned String // user: %1 %1 = thin_to_thick_function %0 : $@convention(thin) () -> @owned String to $@callee_guaranteed () -> @owned String // user: %2 return %1 : $@callee_guaranteed () -> @owned String // id: %2 } // end sil function '$S4test13DEFAULT_CONST1xySSyXK_tFfA_' // implicit closure #1 in default argument 0 of DEFAULT_CONST(x:) sil shared [transparent] [thunk] [always_inline] @$S4test13DEFAULT_CONST1xySSyXK_tFfA_SSyXAfu_ : $@convention(thin) () -> @owned String { bb0: %0 = integer_literal $Builtin.Int64, -2305843009213693952 // user: %1 %1 = struct $UInt (%0 : $Builtin.Int64) // user: %2 %2 = value_to_bridge_object %1 : $UInt // users: %8, %3 %3 = struct $_StringObject (%2 : $Builtin.BridgeObject) // user: %6 %4 = integer_literal $Builtin.Int64, 0 // user: %5 %5 = struct $UInt (%4 : $Builtin.Int64) // user: %6 %6 = struct $_StringGuts (%3 : $_StringObject, %5 : $UInt) // user: %7 %7 = struct $String (%6 : $_StringGuts) // user: %9 strong_retain %2 : $Builtin.BridgeObject // id: %8 return %7 : $String // id: %9 } // end sil function '$S4test13DEFAULT_CONST1xySSyXK_tFfA_SSyXAfu_'
6:33 AM
= "" // default argument 0 of EMPTY_LITERAL(x:) sil non_abi @$S4test13EMPTY_LITERAL1xySSyXK_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> @owned String { bb0: // function_ref implicit closure #1 in default argument 0 of EMPTY_LITERAL(x:) %0 = function_ref @$S4test13EMPTY_LITERAL1xySSyXK_tFfA_SSyXAfu_ : $@convention(thin) () -> @owned String // user: %1 %1 = thin_to_thick_function %0 : $@convention(thin) () -> @owned String to $@callee_guaranteed () -> @owned String // user: %2 return %1 : $@callee_guaranteed () -> @owned String // id: %2 } // end sil function '$S4test13EMPTY_LITERAL1xySSyXK_tFfA_' // implicit closure #1 in default argument 0 of EMPTY_LITERAL(x:) sil shared [transparent] @$S4test13EMPTY_LITERAL1xySSyXK_tFfA_SSyXAfu_ : $@convention(thin) () -> @owned String { bb0: %0 = string_literal utf8 "" // user: %4 %1 = integer_literal $Builtin.Word, 0 // user: %4 %2 = integer_literal $Builtin.Int1, -1 // user: %4 // function_ref specialized String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %3 = function_ref @$SSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfCTf4nnnd_n : $@convention(thin) (Builtin.RawPointer, Builtin.Word, Builtin.Int1) -> @owned String // user: %4 %4 = apply %3(%0, %1, %2) : $@convention(thin) (Builtin.RawPointer, Builtin.Word, Builtin.Int1) -> @owned String // user: %5 return %4 : $String // id: %5 } // end sil function '$S4test13EMPTY_LITERAL1xySSyXK_tFfA_SSyXAfu_'
Avatar
なるほど、じゃあやっぱりパフォーマンスのためなんですかね?
Avatar
omochimetaru 5/24/2018 6:36 AM
パフォーマンスを気にするなら "" を書いてはいけないってのはちょっと嫌だな・・・
Avatar
-emit-ir までいくと完全に同等に。 ; Function Attrs: norecurse nounwind readnone define hidden swiftcc { i8*, %swift.refcounted* } @"$S4test13DEFAULT_CONST1xySSyXK_tFfA_"() local_unnamed_addr #0 { entry: ret { i8*, %swift.refcounted* } { i8* bitcast ({ %swift.bridge*, i64 } ()* @"$S4test13DEFAULT_CONST1xySSyXK_tFfA_SSyXAfu_" to i8*), %swift.refcounted* null } } define linkonce_odr hidden swiftcc { %swift.bridge*, i64 } @"$S4test13DEFAULT_CONST1xySSyXK_tFfA_SSyXAfu_"() #1 { entry: %0 = tail call %swift.bridge* @swift_bridgeObjectRetain(%swift.bridge* inttoptr (i64 -2305843009213693952 to %swift.bridge*)) #2 ret { %swift.bridge*, i64 } { %swift.bridge* inttoptr (i64 -2305843009213693952 to %swift.bridge*), i64 0 } } ; Function Attrs: norecurse nounwind readnone define hidden swiftcc { i8*, %swift.refcounted* } @"$S4test13EMPTY_LITERAL1xySSyXK_tFfA_"() local_unnamed_addr #0 { entry: ret { i8*, %swift.refcounted* } { i8* bitcast ({ %swift.bridge*, i64 } ()* @"$S4test13EMPTY_LITERAL1xySSyXK_tFfA_SSyXAfu_" to i8*), %swift.refcounted* null } } define linkonce_odr hidden swiftcc { %swift.bridge*, i64 } @"$S4test13EMPTY_LITERAL1xySSyXK_tFfA_SSyXAfu_"() #1 { entry: %0 = tail call %swift.bridge* @swift_bridgeObjectRetain(%swift.bridge* inttoptr (i64 -2305843009213693952 to %swift.bridge*)) #2 ret { %swift.bridge*, i64 } { %swift.bridge* inttoptr (i64 -2305843009213693952 to %swift.bridge*), i64 0 } }
Avatar
omochimetaru 5/24/2018 6:39 AM
おお。
6:39 AM
-2305843009213693952 これなんだろう?空の文字列を現すシングルトンのアドレスかなにか?
6:40 AM
固定配置できるのか・・・?
6:52 AM
楽しい感じになってる。
Avatar
ちなみに僕の結果は4.2なので、4.1だと全然違うと思います。
Avatar
omochimetaru 5/24/2018 6:53 AM
StringGutsとかなんかゴリゴリやってますもんね
6:54 AM
なるほど
6:56 AM
var smallUTF8Count: Int の実装を見ると、5..8ビットが文字列の長さ 4bitだから 0..15
6:57 AM
E000.... だから、smallUTF8Count = 0 なので
6:57 AM
空文字列か。
Avatar
omochimetaru 5/30/2018 2:56 AM
So if a class conforms to a protocol with an init requirement, the corresponding init in the class must be required - unless the class is final
2:57 AM
まだ完全に理解していないのでコードで検証する。
Avatar
convenience initが、required init以外のinitを使えるのが悪いんじゃないかな
2:58 AM
required initだけ使えるようになっていればこの問題は起きないと思う (edited)
Avatar
omochimetaru 5/30/2018 3:05 AM
問題が起きるコードがわからない・・・
3:06 AM
protocol P0 { init(string: String) } class Animal { init() {} convenience init(string: String) { self.init() } var str1: String = "" } final class Cat : Animal, P0 { var str2: String = "" } func createP0<X: P0>() -> X { return X.init(string: "apple") } let cat: Cat = createP0() print(cat) ↑特に問題なし
3:08 AM
直接聞いてみるか。
3:13 AM
@omochimetaru It works in 9.3. I think some refactoring I did on master broke it
3:13 AM
Xcode9.3は大丈夫っぽい。
Avatar
omochimetaru 5/30/2018 5:52 AM
5/29スナップショットで再現できた。
Avatar
protocolに定義したassoctypeのconditionを無視してもコンパイル時に発見されず実行時クラッシュが発生するパターンを発見しました。最小コード探すよ。 (edited)
Avatar
omochimetaru 5/30/2018 4:55 PM
これおかしくない? // プロトコルその1, EuclideanRing public protocol EuclideanRing { var eucDegree: Int { get } } // プロトコルその2, Field // そしてFieldならばEuclideanRingである public protocol Field: EuclideanRing {} // それを実現するための実装 extension Field { public var eucDegree: Int { return 0 } } // ジェネリックな型 public struct Complex<R> {} // これはOK //extension Complex: Field {} // これがコンパイルエラー //extension Complex : Field where R == Float {} // error: iOSGround.playground:12:1: error: type 'Complex<R>' does not conform to protocol 'EuclideanRing' // これはOK //extension Complex : EuclideanRing, Field where R == Float {}
4:55 PM
一度話した気もするな。 condconf経由だと間接conformができない
Avatar
それはあれだ、前提になるやつ書かないとエラーになる話
4:55 PM
既出
Avatar
omochimetaru 5/30/2018 4:56 PM
それってそうあるべきで結論になったんだっけ
Avatar
いや、バグでしょって話で、bugsには既存であった、だったかな?そこは覚えてない
Avatar
omochimetaru 5/30/2018 4:56 PM
それともbugsあげたんだっけ
4:56 PM
ふむ
Avatar
型がぶっ壊れるやつはbugsにあげたの覚えてる
Avatar
omochimetaru 5/30/2018 5:00 PM
cond-confのwhere、 == と : の同時定義もだめなんだなあ
Avatar
omochimetaru 6/1/2018 5:06 AM
値型からAnyObjectへ as でboxingできるのが、 ObjectiveC Runtime環境だけで、Linux Swiftではできないのって、なぜなんですっけ。 別に Swift ランタイム側で Swift ネイティブな class に boxing することはできると思う。 (edited)
Avatar
__SwiftObjectかな
Avatar
omochimetaru 6/1/2018 5:07 AM
それをLinuxでも用意できるでしょ?
Avatar
なんやろ
Avatar
omochimetaru 6/1/2018 5:07 AM
class AnyObjectBox { let value: Any }
5:07 AM
↑これでいい
5:08 AM
String と NSString のブリッジングとかは個別に定義されてるし、 それ自体はObjCと関係ない struct と AnyObject の関係が、ObjCかどうかで変化する必要性が思い当たらない。
Avatar
https://github.com/apple/swift/pull/16022https://github.com/apple/swift-corelibs-foundation/pull/1526 でちょうど解決されそうな話題?4.2にもバックポート済み
This patch adopts 'as' bridging on Linux. It requires apple/swift#16022 — see that PR for more details.
Avatar
omochimetaru 6/1/2018 6:24 AM
bridging arbitrary Swift values to opaque (_SwiftValue) reference types and vice versa (with struct X {}: ([X(), X(), X()] as NSArray) as! Array<X>).
6:24 AM
まさにこれだ (edited)
6:25 AM
フムー
6:27 AM
じゃあできるようになる方に統一されるんですね
6:28 AM
そうするともう一個疑問があって、AnyObjectで保持する場合と、Anyで保持する場合で、振る舞いの違いって何があるんだろ
Avatar
Any は値型として振る舞い AnyObject は参照型として振る舞うんじゃないかと思ったけど、 AnyAnyObject に入れたインスタンスのプロパティを変更する方法がなさそう。
Avatar
omochimetaru 6/1/2018 7:57 AM
そうなんですよね、その振る舞いの違いが顕在化するコードはどうなるか試してみたけど、変更を書き戻せないので実際に違いが出せなくて。
Avatar
単に何が入れられるかの違いでは? @swiftbot let i: AnyObject = Int(19) let f: AnyObject = { (a: Int) -> Int in a * 2 } enum E { case none } let e: AnyObject = E.none
🛠 1
Avatar
swiftbot BOT 6/1/2018 9:25 AM
Author icon
masakihori
let i: AnyObject = Int(19) let f: AnyObject = { (a: Int) -> Int in a * 2 } enum E { case none } let e: AnyObject = E.none
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:1:20: error: value of type 'Int' does not conform to specified type 'AnyObject' let i: AnyObject = Int(19) ^~~~~~~ as! AnyObject /usercode/main.swift:2:20: error: value of type '(Int) -> Int' does not conform to specified type 'AnyObject' let f: AnyObject = { (a: Int) -> Int in a * 2 } ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ as! AnyObject /usercode/main.swift:7:22: error: value of type 'E' does not conform to specified type 'AnyObject' let e: AnyObject = E.none ~~^~~~ as! AnyObject
Avatar
@masakihori
値型からAnyObjectへ as でboxingできるのが、 ObjectiveC Runtime環境だけで、Linux Swiftではできないのって、なぜなんですっけ。
じゃあできるようになる方に統一されるんですね
という文脈での話ですね。
9:40 AM
@swiftbot let a: Int = 42 let b: AnyObject = a as AnyObject print(b) print(b as! Int)
🛠 1
Avatar
swiftbot BOT 6/1/2018 9:40 AM
Author icon
koher
let a: Int = 42 let b: AnyObject = a as AnyObject print(b) print(b as! Int)
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:2:22: error: 'Int' is not convertible to 'AnyObject'; did you mean to use 'as!' to force downcast? let b: AnyObject = a as AnyObject ~~^~~~~~~~~~~~ as!
Avatar
↑は Bot は Linux なのでエラーになりますが
9:41 AM
Mac だと↓の結果になります。 _SwiftValue 42
Avatar
AnyはそもそもprotocolなのとAnyObjectはclass型で全然違うような
Avatar
値型の existential は値のように振る舞うのと、イミュータブルクラスは値のように振る舞うのと、値型を AnyObject に入れるとイミュータブルなのとが組み合わさって、挙動が同じように見えるということかと。
Avatar
メモリレイアウトとか違いそう
Avatar
omochimetaru 6/1/2018 10:08 AM
うーん逆に言うと現状だと
10:08 AM
typealais Any = AnyObject 的にコンパイルされていても わからないのでは?ってこと。
10:08 AM
as AnyObjectでboxingしたときに関して。 (edited)
Avatar
値型に関しては、だね。
Avatar
omochimetaru 6/1/2018 10:09 AM
classを入れても同じことになりませんか?
Avatar
いや、参照型も同じか
Avatar
omochimetaru 6/1/2018 10:09 AM
AnyObjectに入れたときも参照共有、Anyに入れたときも参照共有(Anyとしてのコピーのときにインスタンスクローンされない)
Avatar
norio_nomura 6/1/2018 10:28 AM
$ swift Welcome to Apple Swift version 4.1.2 (swiftlang-902.0.54 clang-902.0.39.2). Type :help for assistance. 1> import Foundation 2. 3. var str = "Hello, playground" 4. let a = str as AnyObject 5. let selector = Selector("description") 6. if a.responds(to: selector) { 7. print(a.perform(selector).takeUnretainedValue()) 8. } Hello, playground str: String = "Hello, playground" a: _NSContiguousString = "Hello, playground" selector: Selector = "description"
Avatar
読みたらない上に勉強不足でした
11:18 AM
値型に as AnyObjectがすんなり通るのを知りませんでした
11:20 AM
そうなると確かに AnyとAnyObjectをわける必要性がよくわからないですね
Avatar
omochimetaru 6/1/2018 11:23 AM
@norio_nomura なるほど、 AnyObjectならperfomeSelectoeが使えるという違いはありますねw
Avatar
AnyObjectに明示的にキャストすると幾つかのメソッドがチラ見できる
11:24 AM
@swiftbot import Foundation func foo<T: Any>(x: T) { print(x) } func bar<T: AnyObject>(x: T) { print(x) } foo(x: "") // bar(x: "") // 🙅 bar(x: "" as AnyObject)// 🙆 (edited)
🛠 1
Avatar
swiftbot BOT 6/1/2018 11:24 AM
(edited)
Author icon
tarunon
import Foundation func foo<T: Any>(x: T) { print(x) } func bar<T: AnyObject>(x: T) { print(x) } foo(x: "") // bar(x: "") // 🙅 bar(x: "" as AnyObject)// 🙆
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:13:11: error: 'String' is not convertible to 'AnyObject'; did you mean to use 'as!' to force downcast? bar(x: "" as AnyObject)// 🙆
Avatar
あれ🙅
11:25 AM
ちゃうちゃう
Avatar
omochimetaru 6/1/2018 11:25 AM
最新ならいけるんじゃない?
11:25 AM
さっきのやつマージされてるから
Avatar
謎文字が入っとった
Avatar
omochimetaru 6/1/2018 11:25 AM
4.1はリナックスはだめよ
Avatar
なるほど
11:26 AM
↑で言いたいのは、
11:26 AM
GenericsにAnyとAnyObject指定すると型としての違いが露出するから面白いって話
Avatar
norio_nomura 6/1/2018 11:29 AM
nightlyにもまだ入ってません。
11:34 AM
GitHubのマージコミットページににタグが表示されるかどうかで分かります。 apple/swiftではNightlyに入ってる。 https://github.com/apple/swift/commit/6e5605aee8a230c7f81f3dd1aad716e50e24059b apple/swift-corelibs-foundationではNightlyに入ってない。 https://github.com/apple/swift-corelibs-foundation/commit/1da6fc8ccbce77bfc4cc4fffa6de260ee8589708 (edited)
11:35 AM
Avatar
omochimetaru 6/1/2018 11:42 AM
なるほど、これ見たら良いのか
Avatar
norio_nomura 6/1/2018 11:42 PM
@swift-main @swift-4.2.4 import Foundation func foo<T: Any>(x: T) { print(x) } func bar<T: AnyObject>(x: T) { print(x) } foo(x: "foo") // bar(x: "") // 🙅 bar(x: "bar" as AnyObject)// 🙆 (edited)
Avatar
swiftNightly BOT 6/1/2018 11:42 PM
foo bar (edited)
Avatar
swift42 BOT 6/2/2018 1:55 AM
stderr:<stdin>:13:11: error: 'String' is not convertible to 'AnyObject'; did you mean to use 'as!' to force downcast? bar(x: "" as AnyObject)// 🙆
Avatar
swift42 BOT 6/2/2018 2:42 AM
foo bar (edited)
Avatar
omochimetaru 6/2/2018 6:59 AM
なるほど、キャストする過程は違いますね
6:59 AM
そのままでいいか、asがいるか
6:59 AM
🎉🎊 My contributions landed last night in Swift 4.2 as well. Many casts now work on Linux as well — no more #if os(Linux) for going from NSArray to Array<_>, and JSON parsing will be able to return numbers whose type you don’t have to guess. https://t.co/fLngqlMY3i
7:00 AM
このパッチのオーサーのツイ流れてきた
Avatar
norio_nomura 6/2/2018 1:36 PM
linuxでas? NSObjectが動く様になった事で、今までObjectEncoderのテストがlinuxで期待した通りに動いていなかったことが判明した… 😞 (edited)
🤕 1
Avatar
norio_nomura 6/2/2018 1:49 PM
幸い、DateFormatter.Style.fullの結果がmacOSとLinuxで違ってるのが検出できていない程度で済んだ。 @swift-4.1.3 import Foundation func format(_ date: Date) -> String { let formatter = DateFormatter() formatter.dateStyle = .none formatter.timeStyle = .full formatter.locale = Locale(identifier: "en_US_POSIX") formatter.timeZone = TimeZone(identifier: "GMT") return formatter.string(from: date) } print(format(Date(timeIntervalSince1970: 1000))) // macOS: "12:16:40 AM Greenwich Mean Time" // Linux: "12:16:40 AM GMT" (edited)
Avatar
swift41 BOT 6/2/2018 1:49 PM
12:16:40 AM GMT (edited)
Avatar
@swiftbot --version=3.1.1 func foo(block: (Int, Int) -> Int) {} foo { $0.0 } (edited)
🛠 1
Avatar
swiftbot BOT 6/4/2018 10:01 AM
(edited)
Author icon
kateinoigakukun
func foo(block: (Int, Int) -> Int) {} foo { $0.0 }
Version:
swift-3.1.1-RELEASE
Output:
Error:
Avatar
@swiftbot --version=4.1 func foo(block: (Int, Int) -> Int) {} foo { $0 } (edited)
🛠 1
Avatar
swiftbot BOT 6/4/2018 10:05 AM
(edited)
Author icon
kateinoigakukun
func foo(block: (Int, Int) -> Int) {} foo { $0 }
Version:
swift-4.1-RELEASE
Output:
Error:
/usercode/main.swift:3:5: error: contextual closure type '(Int, Int) -> Int' expects 2 arguments, but 1 was used in closure body foo { $0 } ^ ,<#arg#>
Avatar
swift4で引数がタプルに変換されなくなってから、最初の引数を$で取りたい時どうしてますか?
Avatar
Kishikawa Katsumi 6/4/2018 10:08 AM
$0.0 じゃないですかね。
Avatar
@swiftbot --version=4.1 func foo(block: (Int, Int) -> Int) {} foo { $0.0 }
🛠 1
Avatar
swiftbot BOT 6/4/2018 10:09 AM
Author icon
kateinoigakukun
func foo(block: (Int, Int) -> Int) {} foo { $0.0 }
Version:
swift-4.1-RELEASE
Output:
Error:
/usercode/main.swift:3:5: error: contextual closure type '(Int, Int) -> Int' expects 2 arguments, but 1 was used in closure body foo { $0.0 } ^ ,<#arg#>
Avatar
タプルに変換されないので.0の記法が使えない?
Avatar
どうしても $ で取りたい理由がわかりませんが、 { ($0, $1).0 } とかじゃないと無理かと。
Avatar
コンパイラは$0が1つ目の引数を表しているということを決定できません?
Avatar
技術的に可能かと言われれば可能だと思いますが、現状はそれはやってないですね。
10:17 AM
現状の仕組みとしては、クロージャ内で使われている $n の最大値を使って、例えば { $2 } だとすると、 { ($0, $1, $2) in $2 } と暗黙的に宣言されるようなイメージです。 (edited)
10:18 AM
なのでこの場合 { $0 } はダメだけど { $1 } なら動く。
Avatar
結局$nの最大値が引数の数と一致しないとコンパイル出来ないので、$nの最大値に関わらず引数の数だけ宣言しても問題なくないですか?
Avatar
@swiftbot --version=3.1.1,4.1 let a = { $0 }(1,2,3) print(a)
🛠 1
Avatar
swiftbot BOT 6/4/2018 10:28 AM
Author icon
rintaro
let a = { $0 }(1,2,3) print(a)
Version:
swift-3.1.1-RELEASE
Output:
(1, 2, 3)
Error:
Version:
swift-4.1-RELEASE
Output:
Error:
/usercode/main.swift:1:18: error: extra argument in call let a = { $0 }(1,2,3) ^
Avatar
$0 を単純に第一引数であり、他の引数は無視されると仮定すると、3とそれ以降で同じソースが、エラーも警告も出ずに違う結果を返すことになってしまう可能性があるので、 (edited)
10:31 AM
3 のソースをサポートしている限りはその仕様変更は難しいのだと思います。
Avatar
なるほど!完全に納得できました
🙂 1
Avatar
swift のドキュメントが swift.org に移動した様ですね。 https://docs.swift.org/swift-book/
😀 3
Avatar
norio_nomura 6/5/2018 9:49 AM
お、Using Swift with Cocoa and Objective-Cはどこへ移動したのだろう?
Avatar
norio_nomura 6/5/2018 9:56 AM
大幅に書き換えられてLanguage Interoperabilityに置かれてたぽい。 https://developer.apple.com/documentation/swift#2984801 (edited)
😀 1
Avatar
omochimetaru 6/6/2018 2:11 AM
struct Stone {} let a: Stone.Type = Stone.self let b: Any.Type = a print(MemoryLayout.size(ofValue: a)) // 0 print(MemoryLayout.size(ofValue: b)) // 8
2:11 AM
昨日 @noppe さんと話してて知った↑ゼロバイトの型。
Avatar
↑補足すると、 struct Sample {} // ng unsafeBitCast(Sample.self, to: UnsafeMutablePointer<Int>.self) // ok let type: Any.Type = Sample.self unsafeBitCast(type, to: UnsafeMutablePointer<Int>.self) みたいなコードがあって、コード的に同義じゃないのかなという話からunsafeBitCastのsrc/dstのサイズが実は両者違うという結論の中で出た話です 🦊 (edited)
Avatar
protocolのconformで仕様の壁に当たって困ったことになった (edited)
👀 1
2:01 AM
extension PublicClass: PublicProtocol { associatedtype ProtocolCondition = InternalClass } これができない
Avatar
omochimetaru 6/7/2018 2:02 AM
ああ
Avatar
めちゃくちゃ困った
Avatar
omochimetaru 6/7/2018 2:02 AM
protocolにinternalにconformすることができないから
2:02 AM
protocol経由でいろいろ丸見えになるやつ?
Avatar
全てpublicにしないとconformできない
2:03 AM
しかし、そのprotocolを利用した動きはフレームワークに閉じてるのでそんな滅茶苦茶されるのは困る
2:04 AM
protocolか型の片方はinternalにできるが、assoctypeだけをinternalにできない、そこの非対称性で困ってるって感じですね (edited)
Avatar
omochimetaru 6/7/2018 2:05 AM
あるなあそれ
2:06 AM
できるかわからんけど一回イレイジャ挟む形にすれば隠蔽はできるんじゃないか
Avatar
それはまあそうなんだけど、使い勝手が悪い
Avatar
omochimetaru 6/7/2018 2:06 AM
外向きプロトコルと内部で使うようのプロトコルをわけて定義して、 外向きは内部用へのディスパッチとして実装 内部のやつはAnyHogehogeで包んで実装隠蔽
2:06 AM
だよねえ
Avatar
使い勝手が悪いのは全てpublic太郎に勝てなくなることを意味する
Avatar
omochimetaru 6/7/2018 2:07 AM
俺はむちゃくちゃするやつが悪い!ってことで深く考えない事にした
2:07 AM
シンボルが見えてるからって呼び出しちゃだめなんだ基本
Avatar
いや今困ってるのは
2:08 AM
フレームワーク間の繋ぎ混みを神モジュールでprotocolで表現したときに、モジュールAをモジュールBでimportして繋ごうとすると世界が崩壊したやつなので
2:08 AM
これはどうしようもない
Avatar
omochimetaru 6/7/2018 2:09 AM
ふーむ
Avatar
omochimetaru 6/7/2018 1:33 PM
The accepted and implemented SE-0187 says “…we will add Sequence.compact() when it is possible to do so.” It seems to be possible now, and the shorter syntax for a common operation (filtering nils ...
1:33 PM
これできなかった気がするんだけどいつのにかできるようになった・・・?
Avatar
昼間のpublic話、もし仮に出来るとぶっ壊れるケースが有ることがわかって困った
Avatar
omochimetaru 6/7/2018 1:33 PM
あ、かぶった
1:34 PM
Filtering nil elements from the Sequence is very common, therefore we also propose adding a Sequence.compact() function. This function should only be available for sequences of optional elements, which is not expressible in current Swift syntax.
1:34 PM
やっぱできなかったよね?
1:34 PM
これはflattenも例のハック不要になったか?
Avatar
やっぱRustライクにprotocol conforming自体をoverloadできるようになりたいなぁ
1:38 PM
GenericProtocolほしい
Avatar
Parameterized Extensions がなくてもできた? @inlinable public func compact<T>( ) -> [T] where Element == Optional<T> { return _compactMap { $0 } } (edited)
Avatar
これ変な生え方してるのでは
Avatar
↓が必要だと思ってたけど必要なかった? extension<T> Sequence where Element == Optional<T> { public func compact() -> [T] { ... } }
Avatar
僕が壊れてなければこれは壊れてると思います
Avatar
omochimetaru 6/7/2018 2:15 PM
www
Avatar
↓の where 変な気がしたんだけど、できなかったのか自信がなくなった。 public func compact<T>( ) -> [T] where Element == Optional<T> (edited)
Avatar
Elementに制約がないのであらゆるArrayに生えてるように見えるが使えない不完全なものになる (edited)
Avatar
omochimetaru 6/7/2018 2:16 PM
制約ついてるよ
Avatar
外側でついてない
Avatar
omochimetaru 6/7/2018 2:17 PM
うむ、内側でついてるね。
Avatar
extension側の宣言がが無法地帯では
2:17 PM
内側でつけると壊れる
Avatar
なんか最近内側でつけるの他のとこでも見て、そのときもこんなのできるんだっけ??って思った。
Avatar
残念ながら
Avatar
最近見てたのだから、 KeyPath か SceneKit か ARKit かだと思う。 KeyPath がありそう。
Avatar
前書いたことあるんですが、型推論の全く効かない妙ちくりんになりますね。
Avatar
@swiftbot extension Sequence { public func compact<T>() -> [T] where Element == Optional<T> { return _compactMap { $0 } } } let a: [Int?] = [nil, 2, 3, nil, 5] let b: [Int] = a.compact() print(b)
🛠 1
Avatar
swiftbot BOT 6/7/2018 2:20 PM
Author icon
koher
extension Sequence { public func compact<T>() -> [T] where Element == Optional<T> { return _compactMap { $0 } } } let a: [Int?] = [nil, 2, 3, nil, 5] let b: [Int] = a.compact() print(b)
Version:
swift-4.1.1-RELEASE
Output:
[2, 3, 5]
Error:
Avatar
普通にできる・・・
2:21 PM
内側で型パラメータを縛るという発想がなかっただけ??
Avatar
@swiftbot extension Sequence { public func compact<T>() -> [T] where Element == Optional<T> { return _compactMap { $0 } } } let a: [Int?] = [nil, 2, 3, nil, 5] let b: [Int] = a.compact().compact() print(b)
🛠 1
Avatar
swiftbot BOT 6/7/2018 2:21 PM
Author icon
tarunon
extension Sequence { public func compact<T>() -> [T] where Element == Optional<T> { return _compactMap { $0 } } } let a: [Int?] = [nil, 2, 3, nil, 5] let b: [Int] = a.compact().compact() print(b)
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:8:28: error: generic parameter 'T' could not be inferred let b: [Int] = a.compact().compact() ^
Avatar
Avatar
ちゃんとエラーにもなってますね・・・
Avatar
以前はこれで壊れてましたね
2:22 PM
後はコード補完が壊れるやつが改善してればまぁ…という感じ、ケータイでは試せない
Avatar
@swift-4.0.3 extension Sequence { public func compact<T>() -> [T] where Element == Optional<T> { return _compactMap { $0 } } } let a: [Int?] = [nil, 2, 3, nil, 5] let b: [Int] = a.compact().compact() print(b)
Avatar
swift40 BOT 6/7/2018 2:22 PM
exit status: 1 with stderr:<stdin>:3:16: error: use of unresolved identifier '_compactMap' return _compactMap { $0 } ^~~~~~~~~~~ <stdin>:8:28: error: generic parameter 'T' could not be inferred let b: [Int] = a.compact().compact() ^
Avatar
@swift-4.0.3 extension Sequence { public func compact<T>() -> [T] where Element == Optional<T> { return compactMap { $0 } } } let a: [Int?] = [nil, 2, 3, nil, 5] let b: [Int] = a.compact() print(b) (edited)
Avatar
swift40 BOT 6/7/2018 2:23 PM
exit status: 1 with stderr:<stdin>:3:16: error: use of unresolved identifier 'compactMap' return compactMap { $0 } ^~~~~~~~~~ <stdin>:2:17: note: did you mean 'compact'? public func compact<T>() -> [T] where Element == Optional<T> { ^ (edited)
Avatar
@swiftbot extension Sequence { public func compact<T>() -> [T] where Element == Optional<T> { return _compactMap { $0 } } } let b: [Int] = [] print(b.compact)
🛠 1
Avatar
swiftbot BOT 6/7/2018 2:23 PM
Author icon
tarunon
extension Sequence { public func compact<T>() -> [T] where Element == Optional<T> { return _compactMap { $0 } } } let b: [Int] = [] print(b.compact)
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:7:9: error: generic parameter 'T' could not be inferred print(b.compact) ^
Avatar
まちがえて _compactMap 呼んでた・・・
2:25 PM
てか、 Swift 4.0.3 だと compactMap がないのか。
2:27 PM
@swiftbot extension Sequence { public func flatten<T>() -> [T] where Element : Sequence, Element.Element == T { return flatMap { $0 } } } let a: [[Int]] = [[2, 3], [5]] let b: [Int] = a.flatten() print(b)
🛠 1
Avatar
swiftbot BOT 6/7/2018 2:27 PM
Author icon
koher
extension Sequence { public func flatten<T>() -> [T] where Element : Sequence, Element.Element == T { return flatMap { $0 } } } let a: [[Int]] = [[2, 3], [5]] let b: [Int] = a.flatten() print(b)
Version:
swift-4.1.1-RELEASE
Output:
[2, 3, 5]
Error:
Avatar
@swift-4.0.3 extension Sequence { public func flatten<T>() -> [T] where Element : Sequence, Element.Element == T { return flatMap { $0 } } } let a: [[Int]] = [[2, 3], [5]] let b: [Int] = a.flatten() print(b)
Avatar
swift40 BOT 6/7/2018 2:27 PM
[2, 3, 5]
Avatar
普通にできるぞ・・・
Avatar
omochimetaru 6/7/2018 2:27 PM
4.0.3でもいけるの!?
Avatar
@swift-4.0.3 extension Sequence { public func flatten<T>() -> [T] where Element : Sequence, Element.Element == T { return flatMap { $0 } } } let a: [[Int]] = [[2, 3], [5]] let b: [Int] = a.flatten() print(b) print(b.flatten())
Avatar
swift40 BOT 6/7/2018 2:28 PM
exit status: 1 with stderr:<stdin>:10:7: error: ambiguous reference to member 'flatten()' print(b.flatten()) ^ Swift.Sequence:27:17: note: found this candidate public func flatten() -> FlattenSequence<Self> ^ <stdin>:2:17: note: found this candidate public func flatten<T>() -> [T] where Element : Sequence, Element.Element == T { ^ Swift.Collection:27:17: note: found this candidate public func flatten() -> FlattenCollection<Self> ^ Swift.BidirectionalCollection:27:17: note: found this candidate public func flatten() -> FlattenBidirectionalCollection<Self> ^
Avatar
omochimetaru 6/7/2018 2:28 PM
さっきのプロポーザルにも今のSwiftじゃ無理って書いてあったし
Avatar
できない方( b.flatten() )もちゃんとコンパイルエラーになった。
2:29 PM
やっぱ、みんな Parameterized Extensions がないと駄目だと思ってた?
Avatar
omochimetaru 6/7/2018 2:29 PM
いや、できなかったはず、内側法も思いついて試したぞ
Avatar
4.0.3 でできてるのはなぜ??
Avatar
omochimetaru 6/7/2018 2:31 PM
I'm trying to write an extension to Array which will allow an array of optional T's to be transformed into an array of non-optional T's. e.g. this could be written as a free function like this: f...
2:32 PM
54点の回答のやつ。
Avatar
Wandbox の Swift 3.1.1 で↓動いた。 extension Sequence { public func flatten<T>() -> [T] where Iterator.Element : Sequence, Iterator.Element.Iterator.Element == T { return flatMap { $0 } } } let a: [[Int]] = [[2, 3], [5]] let b: [Int] = a.flatten() print(b)
2:36 PM
Element のままだと動かなくて Iterator.Element にしないとエラーになったから、ちゃんと Swift 3 だと思う。
Avatar
omochimetaru 6/7/2018 2:36 PM
なんてこった
Avatar
これできるなら Parameterized Extensions いらないのでは?
Avatar
Kishikawa Katsumi 6/7/2018 2:37 PM
@swiftbot --version=3.1.1 extension Sequence { public func flatten<T>() -> [T] where Iterator.Element : Sequence, Iterator.Element.Iterator.Element == T { return flatMap { $0 } } } let a: [[Int]] = [[2, 3], [5]] let b: [Int] = a.flatten() print(b)
🛠 1
Avatar
swiftbot BOT 6/7/2018 2:37 PM
Author icon
kishikawakatsumi
extension Sequence { public func flatten<T>() -> [T] where Iterator.Element : Sequence, Iterator.Element.Iterator.Element == T { return flatMap { $0 } } } let a: [[Int]] = [[2, 3], [5]] let b: [Int] = a.flatten() print(b)
Version:
swift-3.1.1-RELEASE
Output:
[2, 3, 5]
Error:
Avatar
omochimetaru 6/7/2018 2:37 PM
プロトコルコンフォーマンスは無理そう
Avatar
Kishikawa Katsumi 6/7/2018 2:38 PM
下は3.0.1まで入ってる。
Avatar
あ、そうか、 --version で指定できるんでしたね。
Avatar
omochimetaru 6/7/2018 2:39 PM
Compactableみたいな。
Avatar
Compactable 、 Parameterized Extension でも書けなさそう。
2:43 PM
protocol Compactable : Sequence where Sequcne.Element == Optional<???> { func compact() -> [Element.Wrapped] }
Avatar
>> 型推論周りが壊れる
2:50 PM
これにつきるんですが、Sequence全体にメソッドが生えているように見えるので
2:50 PM
使い勝手は頗る悪いです
Avatar
そこはコンパイラが賢くなれば・・・😇
Avatar
厳しいのでは
2:51 PM
Compactable自体は型パラ一個増やせばできますね
2:52 PM
protocol Compactable : Sequence where Element == Optional<Wrapped> { associatedtype Wrapped func compact() -> [Wrapped] } まあConformでコケますけど
Avatar
associatedtype をそっちに持っていけるんですね。 Element も書けるから当たり前か。
Avatar
omochimetaru 6/7/2018 2:58 PM
@swiftbot --versions
Avatar
Kishikawa Katsumi 6/7/2018 2:59 PM
@swiftbot versions
Avatar
swiftbot BOT 6/7/2018 2:59 PM
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
Kishikawa Katsumi 6/7/2018 2:59 PM
すまぬ。
Avatar
omochimetaru 6/7/2018 2:59 PM
また間違えたw
2:59 PM
細かいお作法を忘れがち
Avatar
Kishikawa Katsumi 6/7/2018 2:59 PM
これはBot側で吸収するようにしよう。
Avatar
omochimetaru 6/7/2018 2:59 PM
@swiftbot --versions=3.0.1,3.0.2,3.1,3.1.1 extension Sequence { public func flatten<T>() -> [T] where Iterator.Element : Sequence, Iterator.Element.Iterator.Element == T { return flatMap { $0 } } } let a: [[Int]] = [[2, 3], [5]] let b: [Int] = a.flatten() print(b)
🛠 1
Avatar
swiftbot BOT 6/7/2018 2:59 PM
Author icon
omochimetaru
extension Sequence { public func flatten<T>() -> [T] where Iterator.Element : Sequence, Iterator.Element.Iterator.Element == T { return flatMap { $0 } } } let a: [[Int]] = [[2, 3], [5]] let b: [Int] = a.flatten() print(b)
Version:
swift-4.1.1-RELEASE
Output:
[2, 3, 5]
Error:
Avatar
omochimetaru 6/7/2018 3:00 PM
理解
3:00 PM
@swiftbot versions=3.0.1,3.0.2,3.1,3.1.1 extension Sequence { public func flatten<T>() -> [T] where Iterator.Element : Sequence, Iterator.Element.Iterator.Element == T { return flatMap { $0 } } } let a: [[Int]] = [[2, 3], [5]] let b: [Int] = a.flatten() print(b)
🛠 1
Avatar
swiftbot BOT 6/7/2018 3:00 PM
Author icon
omochimetaru
extension Sequence { public func flatten<T>() -> [T] where Iterator.Element : Sequence, Iterator.Element.Iterator.Element == T { return flatMap { $0 } } } let a: [[Int]] = [[2, 3], [5]] let b: [Int] = a.flatten() print(b)
Version:
swift-4.1.1-RELEASE
Output:
[2, 3, 5]
Error:
Avatar
omochimetaru 6/7/2018 3:00 PM
あれ?
3:00 PM
あ〜〜〜
Avatar
Kishikawa Katsumi 6/7/2018 3:00 PM
オプションの場合は--version
Avatar
omochimetaru 6/7/2018 3:00 PM
@swiftbot --version=3.0.1,3.0.2,3.1,3.1.1 extension Sequence { public func flatten<T>() -> [T] where Iterator.Element : Sequence, Iterator.Element.Iterator.Element == T { return flatMap { $0 } } } let a: [[Int]] = [[2, 3], [5]] let b: [Int] = a.flatten() print(b)
🛠 1
Avatar
swiftbot BOT 6/7/2018 3:00 PM
Author icon
omochimetaru
extension Sequence { public func flatten<T>() -> [T] where Iterator.Element : Sequence, Iterator.Element.Iterator.Element == T { return flatMap { $0 } } } let a: [[Int]] = [[2, 3], [5]] let b: [Int] = a.flatten() print(b)
Version:
swift-3.0.1-RELEASE
Output:
Error:
0 swift 0x0000000003350548 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40 1 swift 0x000000000334ed46 llvm::sys::RunSignalHandlers() + 54 2 swift 0x0000000003351076 3 libpthread.so.0 0x00007fd48f4d8390 4 swift 0x0000000001154f30 swift::TypeBase::getDesugaredType() + 32 5 swift 0x0000000001018bf5 swift::ArchetypeBuilder::resolveArchetype(swift::Type) + 21 6 swift 0x000000000101882b swift::ArchetypeBuilder::PotentialArchetype::getType(swift::ArchetypeBuilder&) + 1915 7 swift 0x000000000101d575 swift::ArchetypeBuilder::getArchetype(swift::GenericTypeParamDecl*) + 53 8 swift 0x0000000000f0c29f swift::TypeChecker::finalizeGenericParamList(swift::ArchetypeBuilder&, swift::GenericParamList*, swift::DeclContext*) + 191 9 swift 0x0000000000ee0f39 10 swift 0x0000000000ed15ed 11 swift 0x0000000000edd06b 12 swift 0x0000000000ed14a0 ...
Version:
swift-3.0.2-RELEASE
Output:
Error:
0 swift 0x00000000035c3c08 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40 1 swift 0x00000000035c4367 2 libpthread.so.0 0x00007f1c9a644390 3 swift 0x00000000011be630 swift::TypeBase::getDesugaredType() + 32 4 swift 0x000000000107ab85 swift::ArchetypeBuilder::resolveArchetype(swift::Type) + 21 5 swift 0x000000000107a598 swift::ArchetypeBuilder::PotentialArchetype::getType(swift::ArchetypeBuilder&) + 1400 6 swift 0x000000000107f6e7 swift::ArchetypeBuilder::getArchetype(swift::GenericTypeParamDecl*) + 167 7 swift 0x0000000000f6c87f swift::TypeChecker::finalizeGenericParamList(swift::ArchetypeBuilder&, swift::GenericParamList*, swift::DeclContext*) + 191 8 swift 0x0000000000f4173c 9 swift 0x0000000000f301a9 10 swift 0x0000000000f3d70b 11 swift 0x0000000000f3003b 12 swift 0x0000000000f2ffbd swift::TypeChecker::typeCheckDecl(swift::Decl*, bool) + 157 ...
Version:
swift-3.1-RELEASE
Output:
[2, 3, 5]
Error:
Version:
swift-3.1.1-RELEASE
Output:
[2, 3, 5]
Error:
3:00 PM
3:00 PM
Avatar
omochimetaru 6/7/2018 3:01 PM
3.0属がクラッシュしたぞ
Avatar
Kishikawa Katsumi 6/7/2018 3:01 PM
複数与えるのは後から入った仕様。これもBotで吸収しよう。
🙏 1
Avatar
omochimetaru 6/7/2018 3:01 PM
3.1世代でできるようになっていたのか・・・?
3:02 PM
マジ・・・?あれえ・・・
Avatar
いくらなんでも compactMap の Proposal が書かれる前だね・・・
Avatar
omochimetaru 6/7/2018 3:03 PM
The accepted and implemented SE-0187 says “…we will add Sequence.compact() when it is possible to do so.” It seems to be possible now, and the shorter syntax for a common operation (filtering nils ...
3:03 PM
今入れ違いでclosedになってるw
3:04 PM
Hm, according to this Evolution thread we would better wait for the real deal (extension Sequence where Element : Optional), since going with the temporary generic solution now would cause problems with ABI stability later.
Avatar
かなしい・・・
Avatar
omochimetaru 6/7/2018 3:05 PM
This function should only be available for sequences of optional elements, which is not expressible in current Swift syntax.
3:05 PM
proposalのこれは、
3:05 PM
外側につけることはできないって話だったのか・・・?
Avatar
どうせ ABI 安定化してないんだから別に暫定でこれでもいい気もするけど・・・
Avatar
omochimetaru 6/7/2018 3:06 PM
たしかにw
Avatar
これが駄目だったら、 CodableCodable でない Array サポートしてたのとか、 Equatable でない Array== とかもっとひどい気が。
Avatar
omochimetaru 6/7/2018 3:07 PM
まあ、残念なflattenは手元の案件で自前ではやしてたから、ましな書き方になおせるな。
3:07 PM
たしかに。
3:08 PM
型制約がなんとなくそれっぽいだけの代替品が仮実装されてたことは
3:08 PM
過去にたくさんありますね。
Avatar
Because it cannot later be removed after ABI stability. As you demonstrate, you can use it yourself with minimal fuss if you wish. この意見だけで閉じられちゃってるけど、もっと違う判断もありえたような・・・。
Avatar
omochimetaru 6/7/2018 3:12 PM
このスレこの数時間で開いて決着したのか。
3:12 PM
なんかモヤモヤしますね。
Avatar
個人的には型推論壊れるメソッド追加は無しかなぁという感
3:13 PM
それが理由じゃないのはうーんって感じ
Avatar
omochimetaru 6/7/2018 3:13 PM
壊れるっていうのはどういうこと?
Avatar
追加してIntのArrayに.flatまで打ったらわかる
3:14 PM
補完がぶっ壊れる
3:14 PM
ここが壊れるってことはほかに壊れる要素はありそう
Avatar
omochimetaru 6/7/2018 3:15 PM
error: iOSGround.playground:3:3: error: generic parameter 'T' could not be inferred a.compact()
3:15 PM
ああ、出ないべきなのに出るのね
3:16 PM
うーんでも、それはそっちを直すべきなはなしで
3:16 PM
それ言ったら tableView.rx.items だって
3:16 PM
存在しちゃいかんしなあ
Avatar
野生のライブラリとStandardLibraryはちゃうやろw
Avatar
omochimetaru 6/7/2018 3:17 PM
なるほど・・・?
3:17 PM
標準ライブラリにはいまのところ
3:17 PM
確殺パターンは無いのか。
Avatar
個人的にはCodableの妥協追加は最悪の出来事だった
Avatar
omochimetaru 6/7/2018 3:18 PM
ww
Avatar
あれ( Codable )と比べたら型的には壊れてないしいいのではという気持ちになる
Avatar
Conditionくぐらせていくと何処かで崩壊する境目がありそうですけどね
3:20 PM
Dictionary勝手にネスト事件を思い出した
Avatar
omochimetaru 6/7/2018 3:20 PM
あった
Avatar
そういえば最近も勝手にネスト踏んだ。
Avatar
Me too. I had believed that it was impossible to implement compact() without parameterized extensions. @xwu Because ABI stability has not done, if there are no other problems, is it no good to have the proposed implementation of compact() for now and replace it when paramet...
Avatar
omochimetaru 6/8/2018 2:54 AM
おお
Avatar
Will parametrized extensions be available before Swift 5? I realize Swift 5 was delayed a bit, but I didn't think that anyone was even working on implementing parameterized extensions yet.
8:09 AM
Parameterized extensions を実現するのに ABI に手を入れる必要はないのかな?
Avatar
omochimetaru 6/8/2018 8:11 AM
追加的だから大丈夫そうな気はする
8:11 AM
extensionとかのメタデータが拡張可能な形式になってれば。
8:12 AM
あ、でも、parameterized かつ conditional conformance みたいになると
8:12 AM
実質的にgeneric protocolがあるようなもんだから
8:12 AM
今のメタデータ形式からはみ出そうな気も
Avatar
なるほどー。 ABI に手を入れないといけないけど、後方互換性は保たれるのか。
Avatar
このPRは@_inliable@_versionedがエラーになるんですか? https://github.com/apple/swift/pull/17091
Allow @usableFromInline on typealias declarations, but don't enforce it yet. Enforcement is coming in #16586 Don't produce a warning for the old spelling of @_inlineable and @_versioned exc...
Avatar
norio_nomura 6/10/2018 9:32 PM
-swift-versionに関係なくワーニングとなっていたのが、-swift-version 4はワーニング無し、-swift-version 4.2はワーニング、になるのだと思います。
9:37 PM
SwiftNIOを4.2コンパイラでビルドすると、大量のワーニングが出てて不便だったので。
Avatar
そういうことか。SwiftNIOでビルドするとワーニング出るのは確かに不便
Avatar
norio_nomura 6/12/2018 3:05 AM
@swift-4.2.4 -swift-version 4 @_versioned func f() {}
Avatar
no output
Avatar
norio_nomura 6/12/2018 3:05 AM
@swift-4.2.4 -swift-version 4.2 @_versioned func f() {}
Avatar
stderr:<stdin>:1:2: warning: '@_versioned' has been renamed to '@usableFromInline' @_versioned ^~~~~~~~~~ usableFromInline
Avatar
omochimetaru 6/13/2018 4:42 AM
usableFromInlineで決着してたんですね。
4:43 AM
わかりやすい名前だ・・・
Avatar
https://github.com/apple/swift/blob/master/docs/ABI/TypeMetadata.rst#common-metadata-layout Common Metadata Layoutのkindはclass以外はTypeのポインタから-1した箇所から9byte目を参照すればいいのでしょうか…?
swift - The Swift Programming Language
11:55 AM
enum Kind {} func dumpMemory(_ p: UnsafeRawPointer, _ size: Int) { let addr = unsafeBitCast(p, to: Int64.self) let p = p.bindMemory(to: UInt8.self, capacity: size) for i in 0..<size { if i % 8 == 0 { if i != 0 { print() } print(String(format: "[0x%016lx](\(i/8))", addr + Int64(i)), terminator: "") } print(String(format: " %02x", p[i]), terminator: "") } print() } var type: Any.Type = Kind.self let base: UnsafeMutablePointer = unsafeBitCast(type, to: UnsafeMutablePointer<Int64>.self) let metadataPointer = base.advanced(by: -1) let p = UnsafeMutableRawPointer(metadataPointer) dumpMemory(p, 16) struct: 01 enum: 02 protocol: 0c なのでそれっぽい値は出ているのですが、検証として正しいのか…
Avatar
The kind field is a pointer-sized integer that describes the kind of type the metadata describes. This field is at offset 0 from the metadata pointer.
12:14 PM
なので先頭っぽいですけどねぇ、
12:15 PM
struct Struct { } enum Enum { } protocol Protocol { } func kind(_ type: Any.Type) ->  Int { return unsafeBitCast(type, to: UnsafeMutablePointer<Int>.self).pointee } print(kind(Struct.self)) // 1 print(kind(Enum.self)) // 2 print(kind(Protocol.self)) // 12 (edited)
Avatar
確かにこれkind見るだけならvalue witness tableポインタ分考えなくていいので0から見る方がシンプルですね!
9:00 PM
11ヶ月前からLoadableByAddressというSILpassが必須になっていて
9:02 PM
このテストを見ると、
9:03 PM
SILからIRになるところで、値のコピー渡しから、ポインタ渡しに書き換わっているように見える
9:04 PM
でかい値型はポインタ渡ししてコピーコストを抑えるようになってるんだろうか?
9:07 PM
このパスはSILpassなんだけどIRGenステージの開幕で行われる特殊なやつ https://github.com/apple/swift/blob/477d43ef1c92d6352cd0f819bfd5367cfc785d64/lib/IRGen/IRGen.cpp#L711
swift - The Swift Programming Language
9:08 PM
このパスだけで、2800行もある。。
Avatar
CPUのABI的な制限もあった気がする。
Avatar
omochimetaru 6/19/2018 4:04 AM
どういう制限ですか?
4:05 AM
関数呼び出し前後の引数と返り値の受け渡しはスタック経由だから特に無さそうな気もする
4:06 AM
てか、LLVMIRの段階だとその辺も曖昧な気が。
Avatar
Contribute to swift-clang development by creating an account on GitHub.
4:27 AM
target 毎に https://github.com/apple/swift-clang/blob/stable/lib/CodeGen/TargetInfo.cpp の shouldPassIndirectlyForSwift() で定義されているっぽいです。
Contribute to swift-clang development by creating an account on GitHub.
4:29 AM
ちょっとコード追っただけなので、何か勘違いしている可能性は高いですが💦
Avatar
omochimetaru 6/19/2018 4:31 AM
LoadableByAddress.cpp で shouldPassIndirectly を呼んでる場所、検索したけど見つからず。
4:34 AM
これは LLVM-IR から アセンブリ に変換する段じゃないですかね?
4:35 AM
swift-clangとswift-llvmの役割の違いもよくわからないな〜 swift-clangはObjCなどのブリッジで使われてるはずだけど CallingConventionまでここにあるのか。
4:35 AM
ビルドするときは一緒になっちゃうし。。
Avatar
https://github.com/apple/swift/blob/master/lib/IRGen/LoadableByAddress.cpp#L108 の nativeParameterValueSchema に潜ってみてください。
swift - The Swift Programming Language
Avatar
omochimetaru 6/19/2018 4:37 AM
どうもです
Avatar
omochimetaru 6/19/2018 4:46 AM
なってますね、なるほど
Avatar
けど、元のモチベーションは コードサイズの削減みたいですね。 https://bugs.swift.org/browse/SR-3876
Avatar
omochimetaru 6/19/2018 4:47 AM
requiresIndirect()は、LoadableByAddressとは関係なく、GenCall.cppの中からも参照されたりしているので
4:48 AM
ABI起因のindirectionはもともと普遍的に行われていて、
4:48 AM
LoadableByAddressは最適化の観点で追加されつつ、発生条件を満たすからそっちにも組み込まれた、と予想
4:49 AM
でもなんでポインタ渡しにするとコードサイズが減るんだろ。
Avatar
もともと struct 使うとコードサイズが増えちゃうよねっていう話があって、 https://www.skilled.io/u/swiftsummit/swift-with-a-hundred-engineers Uber が Swift の話したときに話題になった。
Tuomas Artman shares the good and the bad from Uber's rewrite
4:50 AM
Binary size の節。
Avatar
omochimetaru 6/19/2018 4:51 AM
ほ〜〜
Avatar
有効化されたときのテスト差分 https://github.com/apple/swift/pull/11295/files#diff-0f2be7d6654e94788d454c9676e2251b 元々要素一つ一つ取り出してたのを、ポインタ先からの memcpy 一発にしてる。小さくはなりそうだw
radar rdar://problem/28680453 re-enable the new calling conventions by default. The new improved module pass adds support for return types and init()s There might be room for further optimizations ...
Avatar
omochimetaru 6/19/2018 5:00 AM
本題とそれますが、これはあれか、CHECKにキャプチャ機能があるのか?
Avatar
omochimetaru 6/19/2018 5:02 AM
なるほどなあ
5:03 AM
元のコードだとstructのコピーがメンバごとのコピーに展開されてるんですねえ
5:04 AM
元の状態だとレジスタ割当になる可能性があってmemcpyにはできないってことかな。
Avatar
ローレベルだとC言語っぽい
Avatar
omochimetaru 6/19/2018 8:48 AM
↑のテストケース (test/IRGen/value_buffers.sil) は、 SILからLLVM-IRへのコンパイルのテストソースで、 テストの入力のSILソースと、 テストの出力のLLVM-IRソースが、同時に書いてあります。
8:49 AM
出力については SIL から見るとコメント文になっていて、 テストランナーが そのコメントの中にある CHECK や CHECK-NEXT といったテストコマンドを読み取っていて、 そのCHECKの右側にあるのが、出力を期待されているLLVM-IRコードです。
Avatar
HelpHiddenなオプションが swiftc 経由だと使えなくて swift -frontend 経由だと使えるのはどういう制御なんじゃ?
12:22 PM
[omochi@omochi-iMacPro s4]$ swiftc -emit-ir -disable-llvm-optzns a.swift <unknown>:0: error: unknown argument: '-disable-llvm-optzns' [omochi@omochi-iMacPro s4]$ swift -frontend -emit-ir -disable-llvm-optzns a.swift (OK)
Avatar
NoDriverOption フラグが付いたオプションは Driver は認識しないのです。 https://github.com/apple/swift/blob/master/include/swift/Option/FrontendOptions.td#L17
swift - The Swift Programming Language
Avatar
あ、HelpHiddenじゃなくてそっちが効いてるのか、ありがとうございます。
12:28 PM
ほんとうだ、 -primary-file とかも swiftc じゃ使えないのか。
12:29 PM
-primary-file使えないとほぼまともにビルドできない気がする・・・
Avatar
-primary-fileswiftcswift -frontend を起動するときに使うための物なので、そのようになってますね。
Avatar
この前ビルドの流れ調べてたんですが、 -emit-moduleを-primary-fileとその他のファイルと一緒に使って それぞれのファイルをpartial moduleにしたあと、 -merge-modulesで1個にする、って感じだったから。
12:30 PM
ふむ・・・
12:30 PM
swift -frontendはswiftcのエイリアス的な存在かと誤解していました
12:31 PM
swift -frontendが一番ローレベルなインターフェースなのか。
Avatar
https://qiita.com/rintaro/items/3ad640e3938207218c20#バッチモード この辺にちらっと書いてます。バッチモード == Driver == swiftc
Swift のコンパイラの開発に手を出してみたい方向けに、コンパイラの全体構成がどうなっているのかを、大まかに説明します。コードリーディングの参考になればいいなと。

Swift コンパイラの構成

僕は...
Avatar
ありがとうございます、なるほど
12:36 PM
実行せずに、コマンドだけを表示したいなら -driver-print-jobs です。
これいいですね
12:39 PM
前述の通りバッチモード( swiftc ) でのコンパイルも、実際にはフロントエンドモードをサブプロセスとして実行しています。
12:39 PM
最近この辺追っかけてたんですが
12:39 PM
厳密にはこのコマンドの再入の処理が、 execvp の直接呼び出しで実装されてて
12:39 PM
fork していないので
12:40 PM
「サブプロセス」では無いかも。 (edited)
Avatar
あれ、そうなんですか。
12:41 PM
最初のmainからまっすぐここに突入する
12:44 PM
// If we don't have to do any cleanup work, just exec the subprocess. if (Level < OutputLevel::Parseable && !ShowDriverTimeCompilation && (SaveTemps || TempFilePaths.empty()) && CompilationRecordPath.empty() && Jobs.size() == 1) { return performSingleCommand(Jobs.front().get()); }
12:45 PM
jobが1つの場合の最適化なのかも。
Avatar
っぽいですね。今ちょうどそこ見てました。
Avatar
exec生で使うプログラムはじめて見た。
Avatar
forkせずに。っていう事ですか?
Avatar
はい。
12:48 PM
だいたいはfork+execでサブプロセス開くところまでを1セットにしてライブラリ化されていると思います (edited)
Avatar
コマンドラインだとたまにやる時ありますね。 argv の調整だけして argv[0] を再度 exec するとか。 (edited)
Avatar
なるほど
Avatar
omochimetaru 6/21/2018 2:10 AM
The Need for Raw I write a lot of code generation apps. Because of this, I could really use some raw strings in my life. Raw strings aren't uncommon in other programming languages. Swift needs to implement them in a way that feels cromulently Swifty. If you don't remember, t...
2:11 AM
Ericaさん、良いスレ立てるなあと思う
Avatar
ドッグバートアイコン見慣れてしまった
Avatar
omochimetaru 6/21/2018 2:13 AM
こんにちは(^o^)丿 ってご存知ですか全世界で1.5億人の読者がいると言われている、アメリカの新聞の4コマ漫画(4コマじゃないけど)です。数年前から、 にて…
2:13 AM
へえーこれ既存キャラだったのか
Avatar
omochimetaru 6/21/2018 2:14 AM
ITMediaで日本語版が掲載されてるのかw
Avatar
let myString: @raw String この記法だと型がrawに見えてしまうような
2:20 AM
#rawStringのほうが良さそう
Avatar
↓の構文ってパースできる? ) とか " が足りないときとか。 let codeValue = #rawString("let value = "\(coreName): \(coreValue)"")
4:15 AM
#rawString("a") + #rawString("b")ab になるのか a") + #rawString("b になるのか。
Avatar
omochimetaru 6/21/2018 4:17 AM
開き側の (" を見た時点で 閉じる側が ") になり最短マッチで探すんじゃないですかね
4:17 AM
不足してる場合はファイル末尾に到達してsyntax error
4:17 AM
2つ目のケースは ab になる
4:17 AM
だと思います
Avatar
そうすると ")" という文字列を #rawString で作ることはできない?
Avatar
omochimetaru 6/21/2018 4:19 AM
スレでも書かれてるけど、RawStringの場合はエスケープが不可能なので(エスケープがある時点でRawでないから)
4:19 AM
開き側のオペレータをカスタムできる仕様にすることが多いと思います。
4:19 AM
開き側を表したいコンテンツと衝突しないオペレータにすることで任意のコンテンツを表現できます。
Avatar
なるほど〜。何かの言語もそうだった。
Avatar
omochimetaru 6/21/2018 4:20 AM
だから 「 ")" という文字列」をつくれる
4:20 AM
僕も個別の言語がどういう仕様だったかまでの記憶は曖昧・・・
Avatar
omochimetaru 6/21/2018 1:15 PM
本日の #potatotips の「Swiftで高カインド多相」スライドです! https://t.co/Exm3lrCP8r ライブラリ:https://t.co/N3H11CW9jS
👏 1
1:15 PM
面白かった。
Avatar
Existential自体をprotocolに適合させたいという業が発生しがちになってきた
2:16 AM
またその話題のスレ立ったけどABI固定の前にやるからまってて、とのこと
2:16 AM
and we know we'll need to migrate some standard library type erasers to proper existentials
Avatar
existentialがunstableである限り、abi安定できない状態が続く
Avatar
omochimetaru 6/29/2018 2:17 AM
AnySequenceの定義変更もやはりあるようだね
Avatar
@objcも含めて相当闇が深いけどどう落としどころつけるのかめちゃくちゃ気になる
Avatar
omochimetaru 6/29/2018 2:17 AM
早く大枠を発表してほしいなー Condconf級の重要な進化になる
Avatar
Yes, we know we aren't going to implement generalized existentials before ABI stability, and we know we'll need to migrate some standard library type erasers to proper existentials at some point in the future when we do properly support them.
2:28 AM
ABI 安定化の前には やらない じゃない?
Avatar
omochimetaru 6/29/2018 2:29 AM
ほんとだ!w
Avatar
エッ
2:29 AM
大丈夫なのか
Avatar
omochimetaru 6/29/2018 2:30 AM
思い込みで誤読したか
Avatar
ABI に影響しそうだけどしないのか。
2:32 AM
func foo<S: Sequence>(_ sequence: S) where S.Element == Int { ... }
2:32 AM
↑ができて、スペシャライズされないケースがあるんだから
2:32 AM
ABI レベルではすでにサポートされてる?
Avatar
omochimetaru 6/29/2018 3:11 AM
どういう意味ですか?
3:11 AM
Generalized Existentialはまだ存在しないのと、Existentialはそれが抱えるプロトコル自身にconformしないので、↑の関数にはいずれにせよ渡せないです
Avatar
スペシャライズされない場合、この関数の内部では sequence は existential として扱われてるんじゃないの?
Avatar
omochimetaru 6/29/2018 3:16 AM
この関数の内部での表現はありますね
Avatar
それがすでに実現されているということは、 ABI レベルではすでに generalized existential はサポートされていて、 generarized existential のために ABI に新たに何かを追加する必要はないのかと思ったんだけど、 AnySequence 等を使ってる標準ライブラリの ABI は変わってしまうから stable ではないのかな?
3:18 AM
まあでもそれは API の変更の一種のような気も。
Avatar
omochimetaru 6/29/2018 3:20 AM
「ABI レベルではすでにサポートされてる」というのは、実行時にその概念が取り扱えている って意味で書いたんですね
3:20 AM
ABI安定化の議論のときにいつも出てくるのが
Avatar
Generalized Existential を言語仕様に追加するために、 ABI 仕様を変更する必要があるかどうかという意味でした。
Avatar
omochimetaru 6/29/2018 3:21 AM
コンパイル済みのバイナリを言語バージョンまたいでてもリンクできるか
3:21 AM
という点で
3:21 AM
ただそれで言うと、GenExで実装されなおされたAnySequenceと
3:22 AM
昔のAnySequenceに互換性が無さそうなので
3:22 AM
よくわからなくなってしまう
Avatar
そうなんだけど、 API はまだ安定化しないって言ってるんだから、それって API 変更の範疇な気もする。
3:22 AM
struct から existential に変更。
Avatar
omochimetaru 6/29/2018 3:22 AM
あー
3:23 AM
言語レベルで変更があった場合は
3:23 AM
API変更だから許されるのか
3:23 AM
つまり、言語レベルでは何も変わっていない場合には (edited)
3:23 AM
バイナリレベルでも互換性を保つ というのがABI安定を達成した、ということで
3:24 AM
言語レベルで変化があるのであれば、当然バイナリ互換性も壊れてよい。
3:24 AM
確かにABIに対してはあるとしても追加的変更だけで達成できそうですね。
Avatar
でもよくわかってないのが、 ABI 安定化されたら標準ライブラリはアプリにバンドルされずに OS にバンドルされたものを使うことになると思うんだけど、そうするとそういう型レベルでの変更があった場合ってぶっ壊れる気がするんだけどどうなるんだろう?
Avatar
omochimetaru 6/29/2018 3:27 AM
その場合はだめなんじゃないですかね・・・
Avatar
それって実行するまでわからなくない?
Avatar
omochimetaru 6/29/2018 3:28 AM
やるとしたら、OS側に、Swift Stdlibのバージョンを何世代も持っておく必要がありますね。
3:29 AM
std ver1でビルドされたアプリは、std ver1とリンクしないと動かない
Avatar
古い iOS で実行したら死亡では? (edited)
Avatar
omochimetaru 6/29/2018 3:29 AM
そっちに関してはdeployment targetで守れると思います。
3:30 AM
deployment targetを下げた場合は、OSにstd ver1すらない環境を想定するので、stdlib をアプリにbundleする
3:30 AM
OSにstd ver1があるバージョンをdeployment targetにした場合は、アプリにはstdlibをbundleしないで良い(ただし、std ver1を使う、という情報はメタ情報に書いておく)
Avatar
つまり、 Generalized Existential サポート後も、古い iOS を Deployment Target に指定してビルドすると、AnySequence は existential じゃない AnySequence としてビルドされる?
Avatar
omochimetaru 6/29/2018 3:31 AM
ABI安定化前のiOSをターゲットにしてる場合は
3:31 AM
stdlibをバンドルすればよいので
3:31 AM
最新の挙動になります
3:31 AM
ただしアプリサイズが増える。
Avatar
ABI 安定化後で GenEX サポート前をターゲットとした場合 (edited)
Avatar
omochimetaru 6/29/2018 3:33 AM
iOS 12 : std 無し iOS 13 : std v1 プリイン iOS 14 : std v1 と v2 をプリイン iOS12向けアプリ: stdをバンドル → バンドルしてるからどこでも動く iOS13向けアプリ: std無し、v1想定、アプリサイズ縮小 → iOS13も14もv1を持ってるから動く iOS14向けアプリ : std無し、v2想定、アプリサイズ縮小→iOS14はv2を持ってるから動く (edited)
3:33 AM
理屈ではこういう構造になると思います
Avatar
ということは、やっぱり Deployment Target を変更するだけで AnySequencestruct か existential か変わるってことやんね?
Avatar
omochimetaru 6/29/2018 3:36 AM
いや、↑のパターンだと、どれもexistentialになってる想定です。
3:37 AM
こういう想定でした > std v1 : AnySequenceはexistential, std v2: AnySequence は existential
3:39 AM
ではかりに std v1: AnySequenceはstruct , std v2 : AnySequenceはexistential の場合を考えると
3:39 AM
そうですね、iOS13向けに開発するときは、 v1想定で開発することになるから、structになるってことですね。
3:39 AM
現状でいうと、MacOS SDKとかiOS SDK を古いやつを使ってアプリを作るのと同じ状態ですね
3:40 AM
MacOS SDK、あるバージョンでは struct Nib.Name だったのが、あるバージョンでは typealias Nib.Name = String になっていて、まさにそのようなことがおきた。 (edited)
Avatar
なるほど。
Avatar
omochimetaru 6/29/2018 3:42 AM
iOS SDKとSwift Stdlibの両方がカスタマイズ可能だとややこしそうだから
3:43 AM
iOS SDKのあるバージョンにSwift Stdlibのあるバージョンが内包される
3:43 AM
という形にすることで
3:43 AM
これまでの開発体験とあまり差をうまずに実現できそうな気がしてきた。
Avatar
これまでは Swift 3 サポートとかもあったし、組み合わせになるのでは?
Avatar
omochimetaru 6/29/2018 3:44 AM
あーたしかに・・・
11:25 AM
グーグルは自分達のコーディングコンベンションをフォークしたswiftの中のswift formatコマンドに実装していってるのかな?
Avatar
5月以来の動きですね。Harlan が進めてたと思ったけど、引き継いだのかも?
Avatar
値型と参照型を同じ protocol でまとめることに無理を感じる・・・。 @swiftbot protocol Foo { var a: Int { get set } } struct SFoo : Foo { var a: Int = 1 } class CFoo : Foo { var a: Int = 1 } func bar(_ foo: Foo) -> Int { var foo2 = foo foo2.a += 1 return foo.a + foo2.a } let sFoo = SFoo() print(bar(sFoo)) let cFoo = CFoo() print(bar(cFoo))
🛠 1
Avatar
swiftbot BOT 7/2/2018 1:51 AM
Author icon
koher
protocol Foo { var a: Int { get set } } struct SFoo : Foo { var a: Int = 1 } class CFoo : Foo { var a: Int = 1 } func bar(_ foo: Foo) -> Int { var foo2 = foo foo2.a += 1 return foo.a + foo2.a } let sFoo = SFoo() print(bar(sFoo)) let cFoo = CFoo() print(bar(cFoo))
Version:
swift-4.1.1-RELEASE
Output:
3 4
Error:
Avatar
omochimetaru 7/4/2018 3:45 AM
参照だった場合と値だった場合で代入文の意味が変わるのを両方のケースを考慮しながら書くの無理がある感
3:46 AM
だいたいはprotocolで定義されたメソッド呼び出して終わりみたいな程度で、そこの差は踏まなかったりもするけども
Avatar
norio_nomura 7/9/2018 12:43 PM
デフォルトイニシャライザ、 struct S { var a: Int? var b = 1 var c = "" } ならばinit()ではなくinit(a: Int? = nil, b: Int = 1, c: String = "")にして欲しい。 (edited)
👉 1
Avatar
二つのモジュールで同名の型があるときに、片方がunavailableならambiguous出て欲しくないな〜と思った
4:35 AM
関数のオーバーロードで似た話があった気がする、RxSwiftで踏んだやつかな
Avatar
swtwsのexistentialの話、FixedWidthInteger.randomもそうだったなと思って調べたんですが https://github.com/apple/swift/blob/master/stdlib/public/core/Integers.swift.gyb#L2545-L2548
swift - The Swift Programming Language
3:56 PM
@swift-4.2.4 func testA(a: RandomNumberGenerator) { } func testB(a: inout RandomNumberGenerator) { print(a.next()) } var r: Random = Random.default testA(a: r) // OK testB(a: &r) // error: cannot pass immutable value as inout argument: implicit conversion from 'Random' to 'RandomNumberGenerator' requires a temporary
Avatar
exit status: 1 with stderr:<stdin>:13:10: error: cannot pass immutable value as inout argument: implicit conversion from 'Random' to 'RandomNumberGenerator' requires a temporary testB(a: &r) // error: cannot pass immutable value as inout argument: implicit conversion from 'Random' to 'RandomNumberGenerator' requires a temporary ^~
Avatar
RandmNumberGenerator指定するとよくわからんエラーに
3:57 PM
a,
3:58 PM
型指定Randomになってた。RandomNumberGeneratorにしたら通りますね。 inoutだと渡せない?
Avatar
今更なのですがこの挙動を知りませんでした。@swiftbot class Pen { func write() -> String { preconditionFailure("Must be overridden!") } } class GreenPen: Pen { override func write() -> String { return "Green Inks" } } var pen: Pen = GreenPen() print(pen.write()) // => "Green Inks" が返る。 // 僕は preconditionFailure("Must be overridden!") が実行されると思ってました。。
🛠 1
Avatar
swiftbot BOT 7/19/2018 5:44 AM
Author icon
Ohta
class Pen { func write() -> String { preconditionFailure("Must be overridden!") } } class GreenPen: Pen { override func write() -> String { return "Green Inks" } } var pen: Pen = GreenPen() print(pen.write()) // => "Green Inks" が返る。 // 僕は preconditionFailure("Must be overridden!") が実行されると思ってました。。
Version:
swift-4.1.1-RELEASE
Output:
Green Inks
Error:
Avatar
@n.0939 これはサブタイプポリモーフィズムと呼ばれる(単にポリモーフィズムと呼ばれることが多い)挙動ですね。
Avatar
これができると、↓のようにコードを抽象化できます。 @swift-4.2.4 class Person { let firstName: String let lastName: String var fullName: String { fatalError("Override this.") } init(firstName: String, lastName: String) { self.firstName = firstName self.lastName = lastName } } // 西洋人 class WesternPerson: Person { override var fullName: String { return "\(firstName) \(lastName)" } } // 東洋人 class EasternPerson: Person { override var fullName: String { return "\(lastName) \(firstName)" } } let people: [Person] = [ WesternPerson(firstName: "Albert", lastName: "Einstein"), EasternPerson(firstName: "秀樹", lastName: "湯川"), ] // 西洋人と東洋人が混ざっていても姓と名を正しい順に表示 for person: Person in people { print(person.fullName) }
Avatar
Albert Einstein 湯川 秀樹
Avatar
(すみません。中座してました。ふむ。。)
6:07 AM
(へー!)
6:11 AM
例えばC#で上記のコードをリライトしてみると、 (edited)
6:13 AM
pen2は 実際はGeenPen Typeですが Pen Typeだよ、とコンパイラに?伝えているので、Pen Typeの write() メソッドが呼ばれているようです。 (ここのオンラインコンソール https://dotnetfiddle.net 使ってます) (edited)
Test your C# code online with .NET Fiddle code editor.
Avatar
omochimetaru 7/19/2018 6:14 AM
// This file is a "Hello, world!" in C# language by Mono for wandbox. using System; namespace Wandbox { class Program { static void Main(string[] args) { Pen pen1
6:15 AM
C# の場合は、↑のように、親クラス側では virtual をつけて、子クラス側では override をつけます。
6:15 AM
親クラス側で virtual をつけないと、そのように静的ディスパッチになります。
6:16 AM
言い換えると、 Swiftの仕様は C# の仕様で見ると常に virtual が付いている ようなものです。
👏 1
Avatar
@koher @omochimetaru おー! ありがとうございます。😆
6:20 AM
(今更ながらの恥ずかしい質問でしたが、して良かった。ありがとうございますー) (edited)
Avatar
@n.0939 C++の流れを組むカプセル化・継承・ポリモーフィズムによるオブジェクト指向については昔説明を書いたので、もしお役に立ちそうだったらどうぞ↓。 https://qiita.com/koher/items/6878c80014992900add7
最近オブジェクト指向[^1]について説明する機会が多く、これからもっと多くなりそうなので、文章にまとめることにしました。 オブジェクト指向とは何かという説明はたくさんありますが、 __何のために...
👍 1
Avatar
omochimetaru 7/24/2018 1:09 AM
For now, the accessors have been underscored as _read and _modify. I'll prepare an evolution proposal for this feature which should allow us to remove the underscores or, y'know, rename th...
👀 1
1:10 AM
オーナーシップマニフェストで提案されている、コルーチンによる新しいプロパティアクセサ readとmodifyの実装が出た
1:15 AM
struct SimpleModifyのテストみたいに、セッター(modify)の下請けを参照でとおせるので、
1:15 AM
デリゲートされたプロパティの読み書きでコピーコストがかからない
1:16 AM
var temp = backingX のテストみたいに、 実行コンテキストがコルーチンとして維持されているので、
1:17 AM
ローカル変数の参照を返すことが出来る C++だとdanglingになってしまうような見た目のコードがかける
Avatar
or, y'know, rename them to purple and lettuce
なにこれ?ジョーク?
Avatar
omochimetaru 7/24/2018 1:30 AM
アンダースコア名はEvol通して直すよってことに付随したジョークだと思った
Avatar
purple と lettuce という組み合わせがジョークに使われるほど定番の何かなのかかと思ったけどよくわからない・・・ (edited)
🤔 2
Avatar
https://github.com/apple/swift/pull/17767 unowned が Optional を保持できるようになるそうで。これは嬉しい!
@rjmccall okayed this change in a comment on GitHub pull request: #16237
Avatar
norio_nomura 7/24/2018 9:35 AM
ほう。 @swift-4.2.4 @swift-main import Foundation protocol Protocol : class { func noop() } class SwiftClassBase : Protocol { func noop() { print("noop") } } class SwiftClass : SwiftClassBase { override init() { print("SwiftClass Created") } deinit { print("SwiftClass Destroyed") } } func printState(_ x : SwiftClassBase?) { print((x != nil) ? "is present" : "is nil") } func testSwiftClass() { print("testSwiftClass") // CHECK: testSwiftClass unowned var w : SwiftClassBase? printState(w) // CHECK-NEXT: is nil var c : SwiftClassBase = SwiftClass() // CHECK: SwiftClass Created printState(w) // CHECK-NEXT: is nil w = c printState(w) // CHECK-NEXT: is present c.noop() // CHECK-NEXT: noop c = SwiftClassBase() // CHECK-NEXT: SwiftClass Destroyed } testSwiftClass()
Avatar
swiftNightly BOT 7/24/2018 9:35 AM
testSwiftClass is nil SwiftClass Created is nil is present noop SwiftClass Destroyed
Avatar
exit status: 1 with stderr:<stdin>:28:15: error: 'unowned' may only be applied to class and class-bound protocol types, not 'SwiftClassBase?' unowned var w : SwiftClassBase? ^
Avatar
weak var w: SwiftClassBase? と何が違うんです?
Avatar
@swift-main class C {} func test() { var owner: C? = C() unowned var consumer: C? = owner print(consumer) owner = nil print(consumer) } test()
Avatar
swiftNightly BOT 7/24/2018 10:39 AM
exit status: 134 with stdout:Optional(main.C)stderr:<stdin>:6:9: warning: expression implicitly coerced from 'C?' to 'Any' print(consumer) ^~~~~~~~ <stdin>:6:9: note: provide a default value to avoid this warning print(consumer) ^~~~~~~~ ?? <#default value#> <stdin>:6:9: note: force-unwrap the value to avoid this warning print(consumer) ^~~~~~~~ ! <stdin>:6:9: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(consumer) ^~~~~~~~ as Any <stdin>:8:9: warning: expression implicitly coerced from 'C?' to 'Any' print(consumer) ^~~~~~~~ <stdin>:8:9: note: provide a default value to avoid this warning print(consumer) ^~~~~~~~ ?? <#default value#> <stdin>:8:9: note: force-unwrap the value to avoid this warning print(consumer) ^~~~~~~~ ! <stdin>:8:9: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(consumer) ^~~~~~~~ as Any <stdin>:5:15: warning: variable 'consumer' was never mutated; consider changing to 'let' constant unowned var consumer: C? = owner ~~~ ^ let Fatal error: Attempted to read an unowned reference but object 0x6f92c80 was already deallocatedCurrent stack trace: 0 libswiftCore.so 0x00007f03c10ce84d <unavailable> + 3971149 1 libswiftCore.so 0x00007f03c10cea22 <unavailable> + 3971618 2 libswiftCore.so 0x00007f03c10cff70 swift_unownedRetainStrong + 98 5 swift 0x0000000001041bae <unavailable> + 12852142 6 swift 0x0000000001045cd2 <unavailable> + 12868818 7 swift 0x00000000004fa1d2 <unavailable> + 1024466 8 swift 0x00000000004e0104 <unavailable> + 917764 9 swift 0x00000000004db2ec <
Avatar
開放されてたら nil にならずにトラップしてくれる。正直使いどころは限られてはいますが、僕は何度か欲しかったことがありますね。
Avatar
式の型はnon optionalなのですね
10:43 AM
ん?
10:44 AM
式の型はoptionalだけど、someの場合の参照先が解放された場合は、クラッシュするのか。
Avatar
@swift-main class Cat { func nya() -> String { return "nya" } } unowned var a: Cat? = nil print(a?.nya() ?? "nil") var b: Cat? = Cat() a = b print(a?.nya() ?? "nil") b = nil print(a?.nya() ?? "nil") (edited)
Avatar
swiftNightly BOT 7/24/2018 12:54 PM
exit status: 134 with stdout:nil nyastderr:Fatal error: Attempted to read an unowned reference but object 0x820d200 was already deallocatedCurrent stack trace: 0 libswiftCore.so 0x00007f0abfb4384d <unavailable> + 3971149 1 libswiftCore.so 0x00007f0abfb43a22 <unavailable> + 3971618 2 libswiftCore.so 0x00007f0abfb44f70 swift_unownedRetainStrong + 98 4 swift 0x0000000001041bae <unavailable> + 12852142 5 swift 0x0000000001045cd2 <unavailable> + 12868818 6 swift 0x00000000004fa1d2 <unavailable> + 1024466 7 swift 0x00000000004e0104 <unavailable> + 917764 8 swift 0x00000000004db2ec <unavailable> + 897772 9 swift 0x000000000048aa28 <unavailable> + 567848 10 libc.so.6 0x00007f0ac238b740 __libc_start_main + 240 11 swift 0x00000000004886e9 <unavailable> + 558825 #0 0x0000000004102324 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x4102324) #1 0x00000000041001b2 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x41001b2) #2 0x00000000041024d2 SignalHandler(int) (/usr/bin/swift+0x41024d2) #3 0x00007f0ac3c61390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f0ac23a0428 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35428) #5 0x00007f0ac23a202a abort (/lib/x86_64-linux-gnu/libc.so.6+0x3702a) #6 0x00007f0abfb43852 (/usr/lib/swift/linux/libswiftCore.so+0x3c9852) #7 0x00007f0abfb43a22 (/usr/lib/swift/linux/libswiftCore.so+0x3c9a22) #8 0x00007f0abfb44fd2 swift_unownedRetainStrong (/usr/lib/swift/linux/libswiftCore.so+0x3cafd2) #9 0x00007f0ac40904f2 #10 0x0000000001041bae llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) (/usr/bin/swift+0x1041bae) #11 0x0000000001045cd2 llvm::ExecutionEngine::runFunctionAsMain (edited)
Avatar
.some, .none, .some(released) の 3状態あるのかあ。
Avatar
一応外側はsomeの扱いになるんです?
Avatar
omochimetaru 7/24/2018 4:14 PM
扱いという意味では調べようとした瞬間に落ちるからどちらとも言えないんじゃない?
4:15 PM
内部的には「解放済みのオブジェクト」を参照してるからSome、というかポインタが入ってるはずだけど。
Avatar
ああそうか、実行時はポインタになるから一緒か
4:15 PM
some/none/fatal な感覚だった
Avatar
omochimetaru 7/24/2018 4:15 PM
弱参照というのは解放されてるとnilになるけど内部的には開放された領域を指すアドレスを持っているので。
4:16 PM
型理論的には fatal = Never だから 2 + 0 でやっぱり 2状態Eitherとisomorphicなのかな。おもしろいね。
😀 1
Avatar
全然関係ないけど最近Mirror使ってて、Mirrorから見たlazy propertyはOptionalになってるのを確認した
Avatar
omochimetaru 7/24/2018 4:19 PM
それはlazy propertyの裏にあるbacking fieldが見えてるのかな?Mirrorってcomputed propertyは見えないよね
Avatar
おあ、勘違いしてる可能性ありそう
4:20 PM
@swift-4.1.3 class Cat { lazy var name: Int = 1 } print(Mirror(reflecting: Cat()).children.count) (edited)
Avatar
1 (edited)
Avatar
空で書いたらだめだった
4:21 PM
こうなるの
4:21 PM
countが見えてて
4:22 PM
@swift-4.1.3 class Cat { lazy var name: Int = 1 } print(Mirror(reflecting: Cat()).children.first!) (edited)
Avatar
(label: Optional("name.storage"), value: nil) (edited)
Avatar
omochimetaru 7/24/2018 4:24 PM
もしかして
Avatar
何間違えてるかわからんくなった
Avatar
omochimetaru 7/24/2018 4:24 PM
lazyって解決するときに関数を再代入してる?
4:24 PM
分岐が以後なくなるように。
Avatar
参照されて初めて後置のautoclosureを展開してるように見えていて
Avatar
omochimetaru 7/24/2018 4:25 PM
いや、ちがうか? expression type '(_) -> _' is ambiguous を見てそうおもったけどなんかコンパイルエラーになってる?
Avatar
コンパイルエラーはそう
4:25 PM
なんかミスってる
Avatar
omochimetaru 7/24/2018 4:26 PM
type of Mirror になってて変だな。
Avatar
きたきたこれこれ
4:27 PM
Mirror経由でfoo.storageにアクセスできて
4:27 PM
そこがOptionalになってるんですよ
Avatar
omochimetaru 7/24/2018 4:27 PM
name.storage、それっぽい
Avatar
そしてnilだと後置のautoclosureが展開される
4:28 PM
即ち!謂わばweak,unownedと逆っぽい動きだねって話でした
Avatar
omochimetaru 7/24/2018 4:28 PM
逆?
Avatar
丁度対照的な動きをしてる直感的にそんな
4:29 PM
昔ひらりがweakとlazy組み合わせられないのはなんでじゃと言っていたが、この辺の動きを垣間見るに現状は難しいんだなぁと言うのが腑に落ちた
Avatar
omochimetaru 7/24/2018 4:29 PM
//a.swift class Cat { lazy var name: Int = 1 } swiftc -emit-sil a.swift //a.sil class Cat { lazy var name: Int { get set } @sil_stored final var name.storage: Int? init() deinit }
4:30 PM
SILにしたらわかりやすかった↑
Avatar
後なんか、IBOutletもstorageついとったような気がする
4:33 PM
@swift-4.1.3 class Cat { lazy var name: Int = 1 } class Dog { weak var name: AnyObject? } print(Mirror(reflecting: Cat()).children.first!) print(Mirror(reflecting: Dog()).children.first!)
Avatar
(label: Optional("name.storage"), value: nil) (label: Optional("name"), value: nil)
Avatar
weakがstorageになるかと思ったがそうでもなかったの
Avatar
omochimetaru 7/24/2018 4:33 PM
import Foundation @objc class Cat : NSObject { @IBOutlet var name: Cat? } @objc class Cat : NSObject { @sil_stored @IBOutlet var name: Cat? { get set } @usableFromInline override init() deinit }
4:33 PM
IBOutletはそのままっぽい
Avatar
見間違いぽい
Avatar
ほほー。 @swift-main -Xfrontend -emit-sil class Cat { unowned var parent: Cat? }
Avatar
swiftNightly BOT 7/24/2018 11:34 PM
sil_stage canonical import Builtin import Swift import SwiftShims class Cat { @sil_stored unowned var parent: @sil_unowned Cat? { get set } init() deinit } // main sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Int32, 0 // user: %3 %3 = struct $Int32 (%2 : $Builtin.Int32) // user: %4 return %3 : $Int32 // id: %4 } // end sil function 'main' // Cat.parent.getter sil hidden [transparent] @$S4main3CatC6parentACSgXovg : $@convention(method) (@guaranteed Cat) -> @owned Optional<Cat> { // %0 // users: %2, %1 bb0(%0 : $Cat): debug_value %0 : $Cat, let, name "self", argno 1 // id: %1 %2 = ref_element_addr %0 : $Cat, #Cat.parent // user: %3 %3 = begin_access [read] [dynamic] %2 : $*@sil_unowned Optional<Cat> // users: %4, %6 %4 = load %3 : $*@sil_unowned Optional<Cat> // user: %5 %5 = copy_unowned_value %4 : $@sil_unowned Optional<Cat> // user: %7 end_access %3 : $*@sil_unowned Optional<Cat> // id: %6 return %5 : $Optional<Cat> // id: %7 } // end sil function '$S4main3CatC6parentACSgXovg' // Cat.parent.setter sil hidden [transparent] @$S4main3CatC6parentACSgXovs : $@convention(method) (@owned Optional<Cat>, @guaranteed Cat) -> () { // %0 // users: %12, %6, %2 // %1 // users: %4, %3 bb0(%0 : $Optional<Cat>, %1 : $Cat): debug_value %0 : $Optional<Cat>, let, name "value", argno 1 // id: %2 debug_value %1 : $Cat, let, name "self", argno 2 // id: %3 %4 = ref_element_addr %1 : $Cat, #Cat.parent // user: %5 %5 = begin_access [modify] [dynamic] %4 : $*@sil_unowned Optional<Cat> // users: %9, %8, %11 %6 = ref_to_unowned %0 : $Optional<Cat> to $@sil_unowned Op
Avatar
#beginner-help-archived から移動。
4:48 AM
えー The -Ounchecked mode actually contradicts one of the main goals of swift: to be a safe language. In the past we didn’t see lot of significant performance differences compared to -O (there were some improvements but also some regressions).
4:49 AM
そのわずかな差をがんばるために Memory Ownership とかやってるんじゃないの?
4:49 AM
それとも分岐予測が優秀で本当に差がない?
Avatar
omochimetaru 7/27/2018 4:49 AM
安全な言語を目指すゴールとは反する -O と比べてそんなに差がなかった
(edited)
Avatar
これを捨てて C++ や Rust と戦えるのかな?
Avatar
&+ なり unowned(unsafe) なり使って、プログラマ自身が頑張れってことなのか。
Avatar
omochimetaru 7/27/2018 4:50 AM
まあMemoryOwnershipはコピーコストの回避が主で、 uncheckedは分岐削除が主かなあ
4:51 AM
分岐予測が当たればほぼ大丈夫で安全側に予測するからって大丈夫って感じかなあ。
Avatar
たとえば、 image[x, y] みたいなのでピクセルごとにループしてて、毎回 precondition があったらたとえ分岐予測あってもきつくないかな?
Avatar
omochimetaru 7/27/2018 4:53 AM
So if we replace Ounchecked with an option -unsafe-remove-checks (similar to -assume-single-threaded), as Johannes suggested, this is more like a “at your own risk” thing (regarding performance). For example, it might happen that users see perf regressions from one release to another, using this option.
4:53 AM
-unsafe-remove-checks ってフラグは残るのかしら。 (edited)
4:54 AM
I would suggest going further and removing the code for -unsafe-remove-checks altogether. Even untested code has a cost in terms of maintainability.
4:54 AM
Slavaはそれも消せって言ってたw
Avatar
えー
Avatar
omochimetaru 7/27/2018 4:54 AM
ラトナーは懐疑的っぽいですね
4:55 AM
I don’t necessarily agree. -Ounchecked isn’t “bad”. It is a feature in service of a few specific use cases. If you’d like to remove it, then you should publicly advertise that, and justify it based on the lack of users. Don’t cast value judgements against it and claim it should be removed on moral grounds.
4:55 AM
It is a feature in service of a few specific use cases.
↑僕もこう考えてた
4:56 AM
ラトナ: まあEvolだしてね スラバ: コンパイラオプションってEvolなの?
4:56 AM
このスレおもろいな。
Avatar
コマンドのオプションの変更は UI の変更だから evolution 通してねというやりとりを前にも見た気が。
Avatar
omochimetaru 7/27/2018 4:57 AM
ほー
Avatar
SwiftPM だっけ。
Avatar
omochimetaru 7/27/2018 4:57 AM
I don’t think there is an official policy, but IMO, all major new user visible features are in scope for evolution.
4:57 AM
ラトナーの意見であってオフィシャルポリシーは無いらしいw
4:58 AM
-Ounchecked なくなったらいやだなぁ・・・。
Avatar
omochimetaru 7/27/2018 4:58 AM
スレでは完全に合意形成されたわけではないっぽいですね
Avatar
それなのにベンチマークから消したのか?先走り過ぎじゃない?
Avatar
omochimetaru 7/27/2018 4:58 AM
概ね廃止派が主流という感じでベンチマークはなくなったけど。
4:59 AM
コンパイラのロジックとしては -unsafe-remove-checks がある限りありそう。
Avatar
-unsafe-remove-checks があるならいいと思う。
4:59 AM
最適化の有無とは直交した概念な気も。
Avatar
omochimetaru 7/27/2018 5:00 AM
そうですね。
Avatar
PM追えてないから分からないけど、 swift run を PM に明け渡した時は evol 通しましたよね。
Avatar
omochimetaru 7/27/2018 5:00 AM
でしたね。Evol出てたの覚えてる。 (edited)
5:01 AM
あ、こんな細かいのもわざわざやるんだ・・・って思った。
Avatar
まあ、最適化しないのに -unsafe-remove-checks したいケースというのも思いつかないけど🤔
Avatar
あれ、structのletフィールドってEncoderに反映されるようになったんでしたっけ
9:04 AM
@swift-4.0.3 @swift-4.1.3 import Foundation struct Foo: Codable { let a = 1 } let encoder = JSONEncoder() print(try String(data: encoder.encode(Foo()), encoding: .utf8)) (edited)
Avatar
Optional("{\"a\":1}")stderr:<stdin>:7:7: warning: expression implicitly coerced from 'String?' to Any print(try String(data: encoder.encode(Foo()), encoding: .utf8)) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <stdin>:7:11: note: provide a default value to avoid this warning print(try String(data: encoder.encode(Foo()), encoding: .utf8)) ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ?? <#default value#> <stdin>:7:11: note: force-unwrap the value to avoid this warning print(try String(data: encoder.encode(Foo()), encoding: .utf8)) ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! <stdin>:7:11: note: explicitly cast to Any with 'as Any' to silence this warning print(try String(data: encoder.encode(Foo()), encoding: .utf8)) ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ as Any (edited)
Avatar
Optional("{\"a\":1}")stderr:<stdin>:7:7: warning: expression implicitly coerced from 'String?' to Any print(try String(data: encoder.encode(Foo()), encoding: .utf8)) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <stdin>:7:11: note: provide a default value to avoid this warning print(try String(data: encoder.encode(Foo()), encoding: .utf8)) ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ?? <#default value#> <stdin>:7:11: note: force-unwrap the value to avoid this warning print(try String(data: encoder.encode(Foo()), encoding: .utf8)) ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! <stdin>:7:11: note: explicitly cast to Any with 'as Any' to silence this warning print(try String(data: encoder.encode(Foo()), encoding: .utf8)) ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ as Any (edited)
Avatar
@swift-4.1.3 import Foundation struct HaveCahceObject: Codable { private class Cache: Codable { var cachedString: String? init(from decoder: Decoder) throws { } func encode(to encoder: Encoder) throws { } init() {} } var int: Int { didSet { cache.cachedString = nil } } private let cache = Cache() var string: String { get { if cache.cachedString == nil { cache.cachedString = "\(int)" } return cache.cachedString! } } init(int: Int) { self.int = int } } let object = HaveCahceObject(int: 1) let encoder = JSONEncoder() let decoder = JSONDecoder() print( try decoder.decode(HaveCahceObject.self, from: """ {"int": 123} """.data(using: .utf8)!).string ) print( try String(data: encoder.encode(object), encoding: .utf8)! ) エンコ時にちょっとしたゴミが入るけど消す方法無いかな (edited)
Avatar
exit status: 134 with stderr:swift: /home/buildnode/jenkins/workspace/oss-swift-4.1-package-linux-ubuntu-16_04/swift/lib/IRGen/MetadataLayout.h:173: const swift::irgen::ClassMetadataLayout::StoredMethodInfo &swift::irgen::ClassMetadataLayout::getStoredMethodInfo(swift::SILDeclRef) const: Assertion `it != MethodInfos.end()' failed. #0 0x0000000003f25074 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x3f25074) #1 0x0000000003f253b6 SignalHandler(int) (/usr/bin/swift+0x3f253b6) #2 0x00007f9eb908d390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #3 0x00007f9eb77cc428 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35428) #4 0x00007f9eb77ce02a abort (/lib/x86_64-linux-gnu/libc.so.6+0x3702a) #5 0x00007f9eb77c4bd7 (/lib/x86_64-linux-gnu/libc.so.6+0x2dbd7) #6 0x00007f9eb77c4c82 (/lib/x86_64-linux-gnu/libc.so.6+0x2dc82) #7 0x0000000000614484 swift::irgen::ClassMetadataLayout::getMethodInfo(swift::irgen::IRGenFunction&, swift::SILDeclRef) const (/usr/bin/swift+0x614484) #8 0x00000000005460bc swift::irgen::emitVirtualMethodValue(swift::irgen::IRGenFunction&, llvm::Value*, swift::SILType, swift::SILDeclRef, swift::CanTypeWrapper<swift::SILFunctionType>, bool) (/usr/bin/swift+0x5460bc) #9 0x00000000005dce62 swift::SILInstructionVisitor<(anonymous namespace)::IRGenSILFunction, void>::visit(swift::SILInstruction*) (/usr/bin/swift+0x5dce62) #10 0x00000000005d6242 (anonymous namespace)::IRGenSILFunction::emitSILFunction() (/usr/bin/swift+0x5d6242) #11 0x00000000005d3d3b swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) (/usr/bin/swift+0x5d3d3b) #12 0x00000000004e641b swift::irgen::IRGenerator::emitLazyDefinitions() (/usr/bin/swift+0x4e641b) #13 0x00000000005ad837 performIRGeneration(swift::IRGenOptions&, swift::ModuleDecl*, std::unique_ptr<swift::SILModule, std::default_delete<swift::SILModule> >, llvm::StringRef, llvm::LLVMContext&, swift::SourceFile*, llvm::GlobalVariable**, unsigned int) (/usr/bin/swift+0x5ad837) #14 0x00000000005abfdd swift:: (edited)
Avatar
あれ…
Avatar
@omochimetaru 省略するにはデフォルト値が必要らしい。そりゃそうだ。
case自体を省略するとエンコード・デコードされない。この時、Decodableにするにはdefault valueが必要。
https://qiita.com/_ha1f/items/bf1aad5ea3e927f59f9d

はじめに

Swift 4対応の一つ、Codableについていくつか疑問点を実験しつつ、日本語でまとめました。 元記事は以下ですが、たぶん元記事よりも補足しています。 [Encoding and Decoding Custom...
9:49 AM
@swiftbot struct Foo: Codable { private enum CodingKeys: CodingKey { case a } var a: Int private var _b: String = "" }
🛠 1
Avatar
swiftbot BOT 7/27/2018 9:49 AM
Author icon
koher
struct Foo: Codable { private enum CodingKeys: CodingKey { case a } var a: Int private var _b: String = "" }
Version:
swift-4.1.1-RELEASE
Output:
Error:
Avatar
omochimetaru 7/27/2018 9:49 AM
caseから除去してデフォルトを与えとけばいいのかw
Avatar
前にletがエンコードされないとか話題になってなかったでしたっけ🤔
Avatar
そんな話ありましたっけ??
Avatar
夢の可能性が高くなってきた…
🌛 1
2:27 PM
codable+letで過去ログ検索するとデコード時の挙動について出てきたのでこれが混濁してますね、 (edited)
2:29 PM
さし当たり、 1. Cacheを型に纏める 2. Cacheを除いたCodingKeyを定義する と言うのが手っ取り早そうです
Avatar
norio_nomura 7/27/2018 2:41 PM
デフォルト値付きletはエンコードされるけどデコードされない、って話かな?
Avatar
そうっぽい
Avatar
norio_nomura 7/27/2018 2:53 PM
@swift-4.1.3 import Foundation struct S: Codable { var p1: String let p2 = 1 } let encoder = JSONEncoder() encoder.outputFormatting = .sortedKeys let json = String(data: try encoder.encode(S(p1: "p1")), encoding: .utf8) print(json == """ {"p1":"p1","p2":1} """) // true let s = try JSONDecoder().decode(S.self, from: """ {"p1":"p1","p2":2} """.data(using: .utf8)!) print(s.p2 == 2) // false
👍 1
Avatar
true false
Avatar
@swiftbot struct Foo { var foo: Int var bar: Int var buz: Int init(foo: Int, buz: Int) { self.foo = foo self.bar = foo*3 guard foo < bar && bar > 0 else { fatalError() } self.buz = buz } }
🛠 1
Avatar
swiftbot BOT 7/30/2018 7:16 AM
Author icon
t.ae
struct Foo { var foo: Int var bar: Int var buz: Int init(foo: Int, buz: Int) { self.foo = foo self.bar = foo*3 guard foo < bar && bar > 0 else { fatalError() } self.buz = buz } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:10:28: error: variable 'self.buz' captured by a closure before being initialized guard foo < bar && bar > 0 else { ^
Avatar
謎エラー
Avatar
omochimetaru 7/30/2018 7:17 AM
guardって脱出を想定してるから
Avatar
&& の 右辺が autoclosure でラップされるので
Avatar
omochimetaru 7/30/2018 7:17 AM
buzの初期化前に脱出できない?
Avatar
あーautoclosure
Avatar
omochimetaru 7/30/2018 7:17 AM
&&の右だけ self.bar なのか。
7:18 AM
じゃあ、カンマ区切りの構文で書いたら、回避できる?
Avatar
でもbuzが云々言われるのはおかしい気が
Avatar
omochimetaru 7/30/2018 7:18 AM
buzが初期化されてないのにselfをキャプチャしたっていうエラーでしょ
7:18 AM
文言はちょっと変だけど
Avatar
self がキャプチャされてて、そのプロパティが未初期化っていうエラーですね。
Avatar
ああそうか。buz自体がキャプチャされたみたいに読んでました
7:19 AM
カンマ区切りだと回避できますね
Avatar
omochimetaru 7/30/2018 7:19 AM
カンマ区切りと&&の本質的な違いだ
Avatar
||使いたいときはどうしようもなさそう?
Avatar
omochimetaru 7/30/2018 7:20 AM
not の カンマにして if 使う?
Avatar
ド・モルガンだ
Avatar
let _bar = bar とかで一度変数に逃がして || _bar > 0 などするのが解決方法ではありますが、めんどくさいですね。 (edited)
Avatar
self キャプチャって nonescaping でもダメなんだっけ?
Avatar
omochimetaru 7/30/2018 7:22 AM
なるほどカンマ前で逃がせばキャプチャ回避できるのかw
7:22 AM
賢い・・・
Avatar
ダメなのか。 @swiftbot struct Foo { var a: Int var b: Int init() { a = 2 b = [2, 3, 5].reduce(0) { $0 + $1 + a } } }
🛠 1
Avatar
swiftbot BOT 7/30/2018 7:24 AM
Author icon
koher
struct Foo { var a: Int var b: Int init() { a = 2 b = [2, 3, 5].reduce(0) { $0 + $1 + a } } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:7:33: error: variable 'self.b' captured by a closure before being initialized b = [2, 3, 5].reduce(0) { $0 + $1 + a } ^
Avatar
selfがだめなのはまぁ理解できますね
7:25 AM
autoclosureじゃないならaを明示的にキャプチャすればいけるのかな
Avatar
@swiftbot struct Foo { var a: Int var b: Int init() { a = 2 b = [2, 3, 5].reduce(0) { [a] in $0 + $1 + a } } }
🛠 1
Avatar
swiftbot BOT 7/30/2018 7:26 AM
Author icon
koher
struct Foo { var a: Int var b: Int init() { a = 2 b = [2, 3, 5].reduce(0) { [a] in $0 + $1 + a } } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
Avatar
明示キャプチャは OK
7:27 AM
nonescaping なら未初期化 self キャプチャしても良さそうな気もするけどなぁ。
7:27 AM
autoclosure の問題というより、そっちの問題のような気が。
7:28 AM
もちろん↑で self.b へのアクセスはアウトですが、( nonescaping なら) self.a へのアクセスは許してほしい。 (edited)
Avatar
複雑なことしたいならローカルに同名の変数用意して最後にまとめて代入がわかりやすそう
Avatar
omochimetaru 7/30/2018 7:30 AM
callerから見るとnonescapingなクロージャにわたす行為は
7:30 AM
0回以上のクロージャ呼び出しと等価だから
7:30 AM
while ループがそれと同じだから
7:31 AM
Definitive Initializationの機構としては対応できそう
7:31 AM
あとはキャプチャ機構の方だけど
7:31 AM
nonescapingのときに必ず参照キャプチャになっているなら
7:31 AM
selfが値型だろうが
7:32 AM
不完全selfのコピー方法がわからない問題は回避できるから
7:32 AM
理論上はいけそうですね、実装は大変そうだけど
7:32 AM
キャプチャがコピーキャプチャになるケースが存在するなら、selfが不完全だとそれができないから、ダメそう
Avatar
うん、↓だからそれで許されてることは許してほしい。
0回以上のクロージャ呼び出しと等価だから while ループがそれと同じだから
7:37 AM
一方で、↓もできると便利だけど、 1 回以上実行であることが保証できない( 0 回の可能性がある)からこれは許容できない。 func run(_ f: () -> ()) { f() } var a: Int run { a = 42 } print(a)
Avatar
omochimetaru 7/30/2018 7:37 AM
それ、ほしいですよね
7:38 AM
@invokeExactlyOnce @invokeOnceOrMore
Avatar
let だと 1 回であることを保証しないといけない
7:38 AM
うん、そういうのがあると便利だと思う。
Avatar
omochimetaru 7/30/2018 7:38 AM
前回のwaiwaiswiftcで松本さんともその話した
7:39 AM
この辺の話ってasync/awaitでコルーチン入るときに強化されるのかなあ
Avatar
そのフロー解析はできそうな気がしてるけど、停止判定みたいなことにならないよね?
Avatar
omochimetaru 7/30/2018 7:39 AM
awaitしながらinitしたいですよね
7:39 AM
停止判定問題にはならないですね
7:39 AM
少なくとも確実という場合を保証するだけだから。
Avatar
普通にフローたどって、クロージャーの再帰呼び出しがあっても
7:39 AM
それも再帰的にたどるだけでいけるかな。
Avatar
Hello, I’d like to discuss the opportunity to let functions declare that a closure argument is guaranteed to have been executed when the function has returned. For example:   func f(@noescape(executed) closure: () -> ()) {       closure()   } The expected ad...
Avatar
omochimetaru 7/30/2018 7:40 AM
そうやって条件を拡張していくとだんだん難しくなりそうですね
7:40 AM
2016年!w
7:41 AM
Please, don’t bump threads from years ago like this.
Clearly, you’ve got some thoughts in mind about the topic and it’s fresh on your mind, but by doing this you’re putting the onus on everyone to re-read 60 messages before they can even begin to comment
7:41 AM
最後のコメントが、これめっちゃあるなあと思った。
7:42 AM
60ならまだ軽い方で、200ぐらいある1年前の過去スレから始まるともう気持ちが折れる
Avatar
現在の議論の状態をまとめてくれる人がいないと辛いよね。
7:43 AM
日本語でも辛いのに、英語だと・・・
Avatar
omochimetaru 7/30/2018 7:43 AM
でもそれはそれで中立性がな・・・
Avatar
まあ、そこで中立性が崩れても、足りないのは漏れてると思う人が補えば良いわけで、
Avatar
omochimetaru 7/30/2018 7:44 AM
まあ何もないよりは良いか。
Avatar
これを読んだ人じゃないと新たな議論ができないというのはきつい。
7:44 AM
ただ、誰も全体像を把握してないというのが一番有り得そう・・・
Avatar
あと元の @autoclosure 問題は https://bugs.swift.org/browse/SR-7990
👀 3
Avatar
@omochimetaru やっぱ前から話してるような議論プラットフォームが必要だと思う。
7:48 AM
@omochimetaru
awaitしながらinitしたいですよね
これできるなら mutatingasyncfunc もサポートすることになるのでは?
7:48 AM
できたらうれしいけど原理的にきつい気がするんだけど・・・。
Avatar
omochimetaru 7/30/2018 7:49 AM
ならないとおもいます
7:49 AM
メソッドはすでに存在するオブジェクトに対して実行しないといけないから
7:49 AM
スタックにある場合にコルーチンコンテキストに退避できないけど
7:49 AM
initの場合はallocから async init とわかって呼ばれるから
7:50 AM
static func が Promise<Self> を返す場合と同様で 対応できるはず
Avatar
うーん、たしかに init ならできるか?
Avatar
norio_nomura 8/1/2018 11:36 AM
Making a claim that something will never be the case can feel like an invitation for the universe to prove otherwise. Fortunately for us, Swift lives up to this higher standard thanks to the unlikeliest of types.
11:37 AM
Result<String, Never>だとswitchcase . failure書かなくても良いのか。 @swift-main import Foundation enum Result<Value, Error: Swift.Error> { case success(Value) case failure(Error) } func alwaysSucceeds(_ completion: (Result<String, Never>) -> Void) { completion(.success("yes!")) } alwaysSucceeds { (result) in switch result { case .success(let string): print(string) } }
👀 2
Avatar
swiftNightly BOT 8/1/2018 11:37 AM
yes!
Avatar
Swift 4.2でArrayに生えたshuffled(using:)を試しているのですが、型にProcotolを書くと通らない... import Foundation class A: RandomNumberGenerator {} var a: RandomNumberGenerator = A() [1, 2, 3].shuffled(using: &a) // error: argument passed to call that takes no arguments // [1, 2, 3].shuffled(using: &a) var b = A() [1, 2, 3].shuffled(using: &b) // Success
3:12 PM
shuffledと似たような関数を自分で書くと
3:13 PM
import Foundation func shuffled<T>(using generator: inout T) -> [Int] where T : RandomNumberGenerator { return [] } class A: RandomNumberGenerator {} var a: RandomNumberGenerator = A() shuffled(using: &a) // error: in argument type 'inout RandomNumberGenerator', 'RandomNumberGenerator' does not conform to expected type 'RandomNumberGenerator' // shuffled(using: &a) ^
3:13 PM
'RandomNumberGenerator' does not conform to expected type 'RandomNumberGenerator'ってなんだ...
3:16 PM
これ関係あるかも 関係なさそうだった https://bugs.swift.org/browse/SR-7918?jql=text%20~%20%22RandomNumberGenerator%22 (edited)
Avatar
これって a の型が実際にはExistentialになっているからっていうやつ?
Avatar
ですね
10:51 PM
Existentialで拡張したいときは
10:51 PM
extension Array where Element==Existentialにします。:だと具体型が通る
10:52 PM
@swift-4.2.4 import Foundation func shuffled(using generator: inout RandomNumberGenerator) -> [Int] { return [] } class A: RandomNumberGenerator {} var a: RandomNumberGenerator = A() print(shuffled(using: &a)) どうやろか (edited)
Avatar
[] (edited)
Avatar
ンゴゴ
Avatar
意味がわからない
Avatar
そもそもTにしなくていい
10:54 PM
ほい
Avatar
そうすると、 Array.shuffled(using:) がなぜTを使っているのかという疑問が湧いてきました
Avatar
具体型がほしいからですよ
Avatar
逆にTを使わないと、どういう問題が出るんですか?
Avatar
この場合はinoutで渡してるので、existentialだと実行時のメモリ周りで問題が出てくることになりそう、パフォーマンスが悪い、とか。直感ですが…
Avatar
Tを使うとspecializeされて、ってこと?
Avatar
existentialでmutatingやるのは効率悪そうだなーという雰囲気を感じている
11:09 PM
でもRandom...のprotocolの制約にはmutatingとは書いてないですね、なんでだろう
Avatar
ん? next() が mutating なんじゃないですか?
Avatar
あれ、そうなんですか。ドキュメント読んでるんですが書いてない🤔
Avatar
かいてある!
Avatar
一覧の方には書いてないのか!
Avatar
ここから見ると見えない
11:15 PM
ひどひどのひどだ
😵 1
Avatar
@swift-4.2.4 import Foundation func shuffled(using generator: inout RandomNumberGenerator) -> [Int] { return [] } class A: RandomNumberGenerator {} var a = A() print(shuffled(using: &a)) (edited)
Avatar
exit status: 1 with stderr:<stdin>:10:23: error: cannot pass immutable value as inout argument: implicit conversion from 'A' to 'RandomNumberGenerator' requires a temporary print(shuffled(using: &a)) ^~
Avatar
Tを使わないと、existentialになったものしか渡せなくなるんですね
Avatar
inoutだとそういう縛りが出るのか、それは知らなかったです
Avatar
罠だ。。。
11:41 PM
暗黙的にexistentialを作って渡すことになるけど、そうすると作ったexistentialがvarにはならないからってことですね。
Avatar
暗黙生成のexistentialから元のvar具体型へのフィードバックができないからっぽいですね
11:42 PM
メモリ共有されないのか
Avatar
@hironytic @tarunon なるほど!やっぱり具体型なのか... ありがとうございます!genericsで渡さないようにしてほしい...
Avatar
暗黙生成のexistentialから元のvar具体型へのフィードバックができない
これ意図した挙動なんですかね?
🤔 1
2:08 AM
@swift-4.2.4 protocol Animal {} struct Cat: Animal {} var cat = Cat() var animal: Animal = cat func updateAnimal(_ animal: inout Animal) {} updateAnimal(&animal) updateAnimal(&cat) // エラー
Avatar
swift42 BOT 8/2/2018 2:08 AM
exit status: 1 with stderr:<stdin>:10:14: error: cannot pass immutable value as inout argument: implicit conversion from 'Cat' to 'Animal' requires a temporary updateAnimal(&cat) // エラー
Avatar
@Nonchalant 僕は Swift ではできるだけ Existential (プロトコル型変数や引数)を使わないのをオススメします。パフォーマンスも悪いし。 (edited)
🙇 1
Avatar
@koher なるほど...型の依存関係を解決する関係でパフォーマンスが悪いってことですよね... existentialの関係でサブクラスよりパフォーマンスが悪いのかな
Avatar
Existential container に詰め込まれるからですね。実行時にはそれを展開しなおして処理されますし、メソッドコール等も動的ディスパッチになってしまいます。
😱 1
2:17 AM
ジェネリック関数で型パラメータが特殊化されたらコンパイル時に静的に解決できるので速いです(必ず特殊化されるとは限りませんが)。
Avatar
なるほど...知らなかったです...🙇‍♀️🙇‍♀️🙇‍♀️
2:17 AM
ありがとうございます!
🙂 1
Avatar
ぼくもちゃんと理解できているか怪しいのですが、ukitakaさんのこの記事で細かく説明されています 🙂 https://qiita.com/ukitaka/items/8bcff4348c79d820ba32
iOSのDiscordで定期的にあがる話題として「protocol型の値がそのprotocol自身にconformしていないのはなぜ?」というものがあります。 例えば以下のようなコードです。 ```swift protocol An...
Avatar
暗黙生成のexistentialから元のvar具体型へのフィードバックができない
一応コンパイルエラーになってるってことは認知された問題で防がれている、ぶっ壊れる系ではない
Avatar
意図的にコンパイルエラーにしているならそうですが、普通に作ったらエラーになって、穴を開け忘れてる可能性もあるのかなと。値型を existential container に入れてもインスタンス共有されないとかはがんばってるのに、 inout はできないというのにちょっと違和感を感じたので。
Avatar
Cat 型の変数をinout で渡して Dog が代入されたら困るからじゃないかな。
Avatar
omochimetaru 8/2/2018 3:45 AM
protocol Animal { mutating func eat() } struct StructCat : Animal { var weight: Int = 1 mutating func eat() { weight += 1 } } func feed(animal: Animal) { var animal = animal animal.eat() dump(animal) } feed(animal: StructCat())
3:46 AM
mutating func の呼び出しはできるから、できてもいいじゃないかと思ったんだけど・・・
3:46 AM
もし、できるとすると
3:46 AM
protocol Animal { mutating func eat() mutating func copyFrom(_ other: Self) }
3:46 AM
↑代入は Self を取る mutating func と等価だから、 Selfを使っちゃって、Existentialが使えなくなる
Avatar
Cat 型の変数をinout で渡して Dog が代入されたら困るからじゃないかな。
たしかにこれまずそう。
3:56 AM
inout に existential を渡してるなら CatDog に変えられてもいいけど、 Cat を渡して暗黙的に変換された existential に Dog が書かれたら Cat に書き戻せない。
Avatar
なるほど。existentialの問題というより、単純にvarianceの問題なわけですね。
4:50 AM
@swift-4.2.4 import Foundation class Animal { } class Dog: Animal { } func foo(_ animal: inout Animal) { } var inu = Dog() foo(&inu)
Avatar
swift42 BOT 8/2/2018 4:50 AM
exit status: 1 with stderr:<stdin>:9:5: error: cannot pass immutable value as inout argument: implicit conversion from 'Dog' to 'Animal' requires a temporary foo(&inu) ^~~~
Avatar
omochimetaru 8/2/2018 4:52 AM
普通、Animal型の変数にはDogが代入できるけど、 この場合は実体があるから、書き込みがcontravarianceなのね
Avatar
mutating funcでself書き換えて悪さできないかしら
Avatar
Catmutating funcselfCat だから別の Animal に書き換えれないので無理そう?
Avatar
@swiftbot protocol AnimalProtocol {} extension AnimalProtocol { mutating func replace(with obj: Self) { self = obj } } class AnimalBase : AnimalProtocol {} class Cat: AnimalBase {} class Dog: AnimalBase {} var cat: AnimalBase = Cat() cat.replace(with: Dog()) print(type(of: cat)) a
🛠 1
Avatar
swiftbot BOT 8/2/2018 7:22 AM
Author icon
rintaro
protocol AnimalProtocol {} extension AnimalProtocol { mutating func replace(with obj: Self) { self = obj } } class AnimalBase : AnimalProtocol {} class Cat: AnimalBase {} class Dog: AnimalBase {} var cat: AnimalBase = Cat() cat.replace(with: Dog()) print(type(of: cat))
Version:
swift-4.1.1-RELEASE
Output:
Dog
Error:
Avatar
omochimetaru 8/2/2018 7:22 AM
Avatar
ああ、これはOKか。
Avatar
omochimetaru 8/2/2018 7:23 AM
class変数のmutating funcがvar変更になるやつだ・・・
7:24 AM
でもextensionだと引数にSelfが使えるの穴開きそう
Avatar
@swiftbot protocol AnimalProtocol {} extension AnimalProtocol { init(_with obj: Self) { self = obj } } class AnimalBase : AnimalProtocol { convenience init(with obj: AnimalBase) { self.init(_with: obj) } } class Cat: AnimalBase {} class Dog: AnimalBase {} var cat: Cat = Cat(with: Dog()) print(type(of: cat))
🛠 1
Avatar
swiftbot BOT 8/2/2018 7:26 AM
Author icon
rintaro
protocol AnimalProtocol {} extension AnimalProtocol { init(_with obj: Self) { self = obj } } class AnimalBase : AnimalProtocol { convenience init(with obj: AnimalBase) { self.init(_with: obj) } } class Cat: AnimalBase {} class Dog: AnimalBase {} var cat: Cat = Cat(with: Dog()) print(type(of: cat))
Version:
swift-4.1.1-RELEASE
Output:
Dog
Error:
Avatar
闇が深いのはこっちだ。
Avatar
omochimetaru 8/2/2018 7:28 AM
protocol AnimalProtocol {} extension AnimalProtocol { mutating func replace(with obj: Self) { self = obj } } struct Cat: AnimalProtocol {} struct Dog: AnimalProtocol {} var cat: AnimalProtocol = Cat() cat.replace(with: Dog()) print(type(of: cat)) /* error: iOSGround.playground:6:1: error: member 'replace' cannot be used on value of protocol type 'AnimalProtocol'; use a generic constraint instead cat.replace(with: Dog()) ^~~ ~~~~~~~ */
7:28 AM
セーフだった。
Avatar
@swiftbot protocol AnimalProtocol {} extension AnimalProtocol { init(_with obj: Self) { self = obj } mutating func replace(with obj: Self) { self = obj } } class AnimalBase : AnimalProtocol { convenience init(with obj: AnimalBase) { self.init(_with: obj) } init() {} } class Cat: AnimalBase {} class Dog: AnimalBase {} var cat: Cat = Cat() print(type(of: cat)) cat.replace(with: Cat(with: Dog())) print(type(of: cat))
🛠 1
Avatar
swiftbot BOT 8/2/2018 9:33 AM
Author icon
tarunon
protocol AnimalProtocol {} extension AnimalProtocol { init(_with obj: Self) { self = obj } mutating func replace(with obj: Self) { self = obj } } class AnimalBase : AnimalProtocol { convenience init(with obj: AnimalBase) { self.init(_with: obj) } init() {} } class Cat: AnimalBase {} class Dog: AnimalBase {} var cat: Cat = Cat() print(type(of: cat)) cat.replace(with: Cat(with: Dog())) print(type(of: cat))
Version:
swift-4.1.1-RELEASE
Output:
Cat Dog
Error:
Avatar
組み合わせて後から置き換えもできる
Avatar
omochimetaru 8/2/2018 9:34 AM
ww
9:34 AM
これはまあ replace自体は壊れてないんじゃない?
Avatar
そうね
9:35 AM
その手前で壊れてる
Avatar
omochimetaru 8/2/2018 9:35 AM
Catとしてやってきたdogの時点でバグってる
Avatar
やっぱり Self (というか、それを許容しているプロトコル)と継承を許すクラスは相性が悪いと思うなぁ。
9:40 AM
参照型自体は使いたいケースはあるとして、クラスの継承はやめた方が良いのでは。
Avatar
omochimetaru 8/2/2018 9:43 AM
extension AnimalProtocol { init(_with obj: Self) { self = obj } } class AnimalBase : AnimalProtocol { convenience init(with obj: AnimalBase) { self.init(_with: obj) } } おかしいのは、ここで self.init(_with: ) が呼び出せてしまうことじゃないですか?
9:44 AM
AnimalProtocolが引数に受けてる Self は、 AnimalBase が final で無いのだから
9:44 AM
何かのサブクラスである可能性があって (たとえばCat ) なのに、 obj: AnimalBase を渡せてしまっている
Avatar
SelfAnimalBase だから、 AnimalBase 絡みて init(_with:) が呼び出せるのはおかしくないんじゃない?
Avatar
omochimetaru 8/2/2018 9:47 AM
それでいうと、 AnimalBase で定義された convenience init(with:) が、 Cat で呼び出せるのがおかしい、とも言える。
Avatar
それ呼び出せなかったらサブクラスがサブタイプでなくなるよ。
9:47 AM
まあ init はともかく、一般的なメソッドでも Self については言える話だから。
Avatar
omochimetaru 8/2/2018 9:48 AM
一般的なメソッドではSelfはこの手の制限をちゃんと判定していると思います。
9:48 AM
ついでにいうとstatic methodでも。
9:49 AM
サブタイプでなくなることもにないとおもう、ある型Aのインスタンスがある時、型Aのinitやstaticmethodは、Aのインスタンスのサブタイプ互換性とは関係ないはず
9:49 AM
型自体の static method や init を考慮した メタタイプ?同士のサブタイプ関係の話にはなってくると思うけど
9:50 AM
コンパイラ側の議論でも型的におかしいことはわかっているんだけど
9:50 AM
現状放置されているのは
9:50 AM
ObjectiveCのクラスクラスターパターンを動かすためにこれを悪用していて
9:50 AM
外すと互換性がなくなるうんぬんで
9:51 AM
機能を整理しないといけない (factory init などのアトリビュートを追加するとか)
Avatar
↓は許容されていて、 Self はサブクラスには波及しない。 protocol Animal { func foo(_ x: Self) } class Cat: Animal { func foo(_ x: Cat) {} } class Siamese: Cat { } let siamese = Siamese() siamese.foo(Cat())
Avatar
omochimetaru 8/2/2018 9:51 AM
ってステータスじゃなかったっけ
Avatar
これに関しては convenience init(with obj: AnimalBase) { self.init(_with: obj) // <- ここがSelfチェックなはずのにAnimalBaseが通るのがおかしい } だと思っていて、型として問題があるわけではないと思う
Avatar
omochimetaru 8/2/2018 9:52 AM
↑それは、 self が AnimalBase じゃない Cat である可能性があるからだよね?
Avatar
そう
Avatar
omochimetaru 8/2/2018 9:52 AM
(ここで self はいつものインスタンスselfじゃなくてクラスそれ自体の方
9:53 AM
僕が最初に言ったのもその視点。
9:53 AM
koher が言ってるのは、その行単体でみれば AnimalBase だからおかしくない、って話で
9:53 AM
その視点の場合は、継承先で同じ convenience init が実行されてることがおかしい って言い方になる。
9:54 AM
@koher そのケースは、Selfが引数部だから contravariance が効いていて、 Siamese.foo(x: Siamese) が実装されていると考えることができる。
9:54 AM
なぜなら(というか直感的説明では)、 Cat をうける foo は Siamese も受けられるから。 (edited)
9:55 AM
@koher Self を返り値に使うケースでは covariance が効くのだけどそれだとどうしてもおかしなことになる関係でコンパイラがエラーを出します
Avatar
@swiftbot protocol Animal { func foo() -> Self } class Cat: Animal { func foo() -> Cat { return Cat() } } class Siamese: Cat { } let siamese = Siamese() let cat = siamese.foo()
🛠 1
Avatar
swiftbot BOT 8/2/2018 10:00 AM
Author icon
koher
protocol Animal { func foo() -> Self } class Cat: Animal { func foo() -> Cat { return Cat() } } class Siamese: Cat { } let siamese = Siamese() let cat = siamese.foo()
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:6:10: error: method 'foo()' in non-final class 'Cat' must return `Self` to conform to protocol 'Animal' func foo() -> Cat { return Cat() } ^
Avatar
うーん、それで問題ないのか。
Avatar
omochimetaru 8/2/2018 10:02 AM
これだとコンパイル通る protocol Animal { func foo() -> Self } class Cat: Animal { func foo() -> Self { return self } } class Siamese: Cat { } let siamese = Siamese() let cat = siamese.foo()
10:02 AM
return self 以外にも、 type(of: self).init() などで Self 型の値が作れる。
Avatar
norio_nomura 8/2/2018 10:04 AM
swift-corelibs-foundationのfactory initializerパターンへの書き換えは、随分前に止まっちゃいましたね。
Avatar
omochimetaru 8/2/2018 10:04 AM
このケースだと、Siameseのfooメソッドを呼んだ時は、インスタンスが Siamese なので Self が返ってきてて OK
10:05 AM
@norio_nomura あれ?書き換えってとっくにおわってなかったでしたっけ?
10:05 AM
結局まーじされなかった?
Avatar
NSNumber問題かな
Avatar
omochimetaru 8/2/2018 10:06 AM
ほんとだ・・・
Avatar
最後にrebaseやってくれーと書いてあるw
Avatar
omochimetaru 8/2/2018 10:07 AM
What's in this pull request? I'm not sure this can be accepted or not. But this is convenient in some cases. Using that: Simplify copy constructor of NSSet and NSDictionary Eliminate getVa...
10:08 AM
slavapestov commented on 13 Aug 2016 I don't think assignment to self in a protocol extension initializer is a bug. Now we do want to change the ABI to make factory initializers more efficient, but the language feature is fine.
10:08 AM
2年前のslavaの見解はバグ (誤読) (edited)
10:09 AM
でもこれはあれだね、extensionのほうの self = factory() の式をバグっていっているので (edited)
10:09 AM
さっきの俺とtarunonの考えとはまた違うね。 (edited)
Avatar
フーム
Avatar
omochimetaru 8/2/2018 10:09 AM
(self代入はOK, それを呼び出すconvenience initがダメ
Avatar
「バグではない」という見解ですよ
Avatar
omochimetaru 8/2/2018 10:10 AM
10:10 AM
dontか。
Avatar
これ日本人的にはI think .... isn't a bug って書きたくなる
Avatar
omochimetaru 8/2/2018 10:11 AM
ナンカ前も冒頭のnot読み飛ばして真逆になったんだよな・・・
Avatar
英会話教室でそれは普通使わないって言われました。think ... isn't
Avatar
omochimetaru 8/2/2018 10:13 AM
Swift5が出そうになってきたしこの辺決着つけてほしいなあ
Avatar
norio_nomura 8/2/2018 10:13 AM
全体的な書き換えが止まっただけで、factory initializerパターン自体はまだ残ってますね。 https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSNumber.swift#L675
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
Avatar
omochimetaru 8/2/2018 10:14 AM
ああ、 PR #1095は > Generalize factory patterns for use outside of NSValue NSValue以外のやつらにもやるってPRなんですね。 (edited)
Avatar
norio_nomura 8/2/2018 10:14 AM
そそ。
10:16 AM
Foundationのソースを見られるappleの中の人が、書き換えをしてくれる事を期待したのだけど、ダメだった。
Avatar
omochimetaru 8/2/2018 10:21 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 sub...
10:21 AM
この辺かなあ
10:24 AM
Discourseってレスとレスの間にめっちゃ日にちが立ってると 9 MONTHS LATER みたいに出るのいいね。
Avatar
omochimetaru 8/2/2018 10:55 AM
@swiftbot protocol Assignable { mutating func assign(from other: Self) } extension Assignable { mutating func assign(from other: Self) { self = other } } class Animal : Assignable { func speak() { fatalError() } } class Cat : Animal { override func speak() { print("にゃー") } } class Dog : Animal { override func speak() { print("わん") } } var cat: Animal = Cat() cat.assign(from: Dog()) cat.speak()
🛠 1
Avatar
swiftbot BOT 8/2/2018 10:55 AM
Author icon
omochimetaru
protocol Assignable { mutating func assign(from other: Self) } extension Assignable { mutating func assign(from other: Self) { self = other } } class Animal : Assignable { func speak() { fatalError() } } class Cat : Animal { override func speak() { print("にゃー") } } class Dog : Animal { override func speak() { print("わん") } } var cat: Animal = Cat() cat.assign(from: Dog()) cat.speak()
Version:
swift-4.1.1-RELEASE
Output:
わん
Error:
Avatar
omochimetaru 8/2/2018 10:55 AM
いや、これはいいのか。
Avatar
Self引数をクラスに実装したときに
11:41 AM
extension経由だとその時点のクラスに畳まれる、ここが壊れ
Avatar
omochimetaru 8/9/2018 3:01 AM
https://forums.swift.org/t/value-ownership-when-reading-from-a-storage-declaration/15076 John McCallが新しいオーナーシップ付きのプロパティをどういう文法にしよう?ってピッチを投げてる
Background: Ownership Manifesto As part of preparing the Swift ABI for getting locked down in Swift 5, I am changing some aspects of the implementation strategy for storage accesses in Swift 5. A lot of this is purely implementation-level and has no effect on the language, ...
3:04 AM
このピッチの中で、秘密のアクセサの materializeForSet について解説されているのも面白い
3:06 AM
materializeForSet は Swift で setter のある property を作ると生成される第3のアクセサで
3:07 AM
ストレージのポインタを取得できる関数。 property が stored property で実装されている場合に、それが inout T を取る関数などに渡される場合に、
3:07 AM
stored property の実メモリのポインタを materializeForSet を使って取得してやることで、
3:07 AM
getter / setter のオーバヘッドを回避できるっていうハックなんだけど
3:10 AM
これが modify アクセサ として再設計されるとのこと。 materializeForSet はポインタ参照先が死んでいることが無いように、ユーザは直接使えないけど、 modify アクセサは言語機能として搭載されるコルーチンを使った実装になるので、 言語仕様として見えるようになる。
😃 1
Avatar
omochimetaru 8/13/2018 4:12 AM
As you can probably tell, I've been saving a lot of discussions, waiting for Swift 4.2 to be in a pretty good place before we jump all in on Swift 5. This one's one of the main things I plan to be working on in the next year or so, so I wanted to make sure you all had the big...
4:13 AM
興味深いスレッド。Swift5でのABI stabilityをどうすすめるかの話。
4:13 AM
.swiftinterface っていうライブラリのヘッダとして使われるテキストファイルを新しく導入するアイデアらしい。
4:13 AM
.swiftinterface.swift から自動生成される。
4:14 AM
あと 「ABI Stability」について定義されてる。
4:21 AM
(なんかスレは virl って人がめっちゃ暴れてるな・・・
Avatar
omochimetaru 8/13/2018 4:28 AM
勘違い諭されて静かになってる
Avatar
Kishikawa Katsumi 8/15/2018 12:12 PM
https://forums.swift.org/t/isnotempty-on-array/15228/25 これオシャレで良いなあと思いました。
As you might surmise, I don't have any specific generic algorithm an Emptiable protocol would enable. I find it interesting for two reasons: Clarity: I find "isInhabited" to be much clearer and easier to reason about than "isEmpty == false" & "!isEmpty" (& even "isNonEmpty...
12:13 PM
@inverse(isNotEmpty) var isEmpty: Bool { ... } ^ ここのところ。
Avatar
オシャンですが個人的にはBoolを特別扱いしすぎでウーンって感じがします
3:01 PM
この手合いのことをやるならJavaのアノテーションみたく一般化するべきかなぁとは思うのですがその先は地獄だし
Avatar
omochimetaru 8/15/2018 3:01 PM
これすごい悩ましい。 isXxx全てに対してisNotXxxを考えることができるのでキリが無くなる。 でもisEmptyがわかりにくいのはわかる。
3:02 PM
isNotXxx実装する路線でいくなら実装ミスが無いアノテーション作戦は良い
3:03 PM
メソッドに付与することでメソッド実装を静的に自動生成するコンパイル時高階関数であると考えれば、 TypeScriptなんかのデコレータって言語機能に相当すると思う。
Avatar
やるなら一般化するべき&しかしabuseされて地獄になる未来、の両方が見えてる
Avatar
omochimetaru 8/15/2018 3:04 PM
このスレでも出てくるんだけど NonEmptySequence 型よさそうで
Avatar
それはほしいわかる
Avatar
omochimetaru 8/15/2018 3:05 PM
firstやlastが T? じゃなくて T になる型
3:05 PM
Sequenceにたいして、 var nonEmptySequence: NonEmptySequence? を提供してやると
3:05 PM
guard let _ = array.notEmptySequence
3:06 PM
と書けるってのはどうだい、みたいなレスもあった。
Avatar
高階kindなしでやると
Avatar
omochimetaru 8/15/2018 3:06 PM
そうだねえw
Avatar
そもそもNonEmptySeqはProtocolじゃなくていいはず
3:06 PM
structでSeqの実装でfirst/lastがnon optional実装なだけでいい (edited)
Avatar
omochimetaru 8/15/2018 3:07 PM
元のコレクションに対応したNonEmpty版の型を返すべきだがそれうまくprotocolにならなそう
Avatar
それは高階kind必須
3:08 PM
いや?
3:08 PM
取って置きのワークアラウンド思いついたわ
3:09 PM
struct NonEmptySeq<S>: Sequence where S: Sequence { typealias Element=S.Element }
3:09 PM
なんかこんな感じでなんとかなるやろ
3:10 PM
何チャラIndexがこんな感じの実装になってませんでしたっけ
Avatar
omochimetaru 8/15/2018 3:10 PM
Iteratorとかがそんなんだったような
Avatar
だよねだよね
3:11 PM
でも脳に優しくないからやっぱ高階kindほしいわ
Avatar
omochimetaru 8/15/2018 3:11 PM
This is not a problem at all if you store the underlying collection in a single property rather than separating the first element from the rest.
3:11 PM
NonEmptyスレ
3:12 PM
@inverse の人も書き込んでるね
Avatar
便利は便利だけどやりすぎかなーみたいな気がしてきた
3:20 PM
これって結局UIntだけじゃ満足できませんってんでNonZeroUInt入れましょうって言ってるのとそんなに変わらん (edited)
Avatar
omochimetaru 8/15/2018 3:20 PM
Even And Odd Integers DISCLAIMER: This is not a proposal, just an idea Several times recently I have been forced to identify even elements for the purposes of analyzing an array or other, similar groupings of data. After the second time I simply extended Int and added an is...
3:21 PM
整数じゃ満足できなくなって奇数・偶数が欲しい人↑
Avatar
じゃけん7の剰余で7個の型作りましょうね
3:22 PM
いやーないでしょ
Avatar
omochimetaru 8/15/2018 3:22 PM
証明言語とかだとできそうだけどね
3:22 PM
型パラメータの代わりに値の制約式みたいなのが書けるやつ。 (edited)
Avatar
数値を型にできるやつなら
Avatar
omochimetaru 8/15/2018 3:23 PM
これおもしろいのがさ
Avatar
Mod<A,N>でいい
Avatar
omochimetaru 8/15/2018 3:23 PM
@inverse(isOdd) var isEven: Bool
3:23 PM
なんだよねw
Avatar
あれれー
Avatar
omochimetaru 8/15/2018 3:24 PM
isXxxのinverseがisNotXxxじゃない稀な例 (edited)
Avatar
いやそんなこといったら
3:24 PM
別にisEmptyの対もisNotEmptyじゃなくてもいいでしょ
Avatar
omochimetaru 8/15/2018 3:24 PM
ruby on rails だと present? ですね
Avatar
そっちの方が分かりやすいじゃん
3:26 PM
二重否定が許されるのは日本語だけだぞ
Avatar
omochimetaru 8/15/2018 3:27 PM
presentとemptyがあったらこれらが本当に単に逆の意味なのか、 微妙にすれ違って同軸上に無い概念なのか心配にならない?
Avatar
流石にcollectionでそれは無いのでは
3:28 PM
IntでisPlusとisMinusがあったら死人は出そうである
Avatar
omochimetaru 8/15/2018 3:28 PM
それうけるなw
Avatar
isPlus contains zero(出展はCS)
3:29 PM
盛り上がって参りました
Avatar
omochimetaru 8/15/2018 3:29 PM
enum Sign { case plus; case zero; case minus }
Avatar
Floatだと+0と-0って明示できないかな、ちょうど0になるんでしたっけ?
3:32 PM
こんなのみつけた
Avatar
omochimetaru 8/15/2018 3:34 PM
Floatはカオスよ
Avatar
なるほどなー
Avatar
omochimetaru 8/15/2018 3:35 PM
Floatのせいで Equatable は @inverse(!=) func == にできません
Avatar
nanがいるからだっけ
Avatar
omochimetaru 8/15/2018 3:35 PM
うん。
Avatar
non empty collection 、値型だとうまくいかない気がする。
1:29 AM
Ceylon が 1.0 のときは non empty collection を持ってたけどいつの間にかなくなってた気がする。
Avatar
omochimetaru 8/16/2018 1:30 AM
中身見てないですけど、スレッドにはライブラリ実装が投稿されてますよ
Avatar
実装はできるけど、↓になるという意味。 let nonEmpty = [42] let maybeEmpty: [Int] = nonEmpty // コンパイルエラー
Avatar
omochimetaru 8/16/2018 1:45 AM
なるほど
Avatar
それはArray優先じゃないですかね
Avatar
NonEmptyListList のサブタイプにできない。
Avatar
明示したときだけNonEmptyにするべきだし、サブタイプ関係は無いです
Avatar
うーん、 non empty をわざわざ扱えるようにするなら↓はできてほしい気が。 let a = [2, 3, 5] print(a.first + 1)
Avatar
明示するべきです
Avatar
あと、 NonEmptyArrayArray 型の引数に渡せなくなって、全部オーバーロードするとかになりますし、
Avatar
NEAとArrayのサブタイプ関係は嘘と直感が囁いている
1:48 AM
ちゃんと考えてないけど、それを認めるとOptionalと同様の崩壊を引き起こすと思います
Avatar
NonZeroUInt とかも、サブタイピングがあれば別にいいと思うんですよね。
1:49 AM
数学的には自然数は整数だし、整数は実数だし、実数は複素数だし。
Avatar
omochimetaru 8/16/2018 1:50 AM
Optionalが崩壊してるのは二重にできることとArrayの空配列が互換性がある事のまわりだけなきがする
1:50 AM
NonEmptyはArrayに1度だけくっつく属性だから違いそう(任意のTをつつめる型ではない
Avatar
NEA<Array<Int>>.flatten()とか
1:51 AM
Array<NEA<Int>>.flatten()とか
1:52 AM
この辺がヤバそう
1:52 AM
これはNEA<NEA>だけがNEAになれるはずだが、
Avatar
omochimetaru 8/16/2018 1:52 AM
いずれにせよ現状の型システムだとサブタイピングはできないからコンパイラサポートがいりそう
Avatar
なので、 NEA<NEA> のときの conditional なオーバーロードを作ることになると思います。
Avatar
omochimetaru 8/16/2018 1:53 AM
まあ現状だと、
1:53 AM
appendしたあとで first! って書くのにくらべたら
1:53 AM
明示的な変換があってもNonEmptyな型があったら
1:53 AM
便利だなと思う
Avatar
@omochimetaru それはそれで微妙で、 ArrayArraySlice とか、あえて明示的に変換するのが Swift の(というか値型の?)スタイルだから、暗黙変換は Swift になじまないと思う。 < サブタイピングはできないからコンパイラサポートがいりそう (edited)
1:55 AM
まあ、プロトコルレベルで継承関係作ってれば、それなりに便利かも?
Avatar
いややっぱこれ、高階カインド無しにはやるのはちょっと…って感じしますね
Avatar
protocol NonEmptySequence: Sequence { ... } func max<S: Sequence>(_ sequence: S) -> S.Element? where S.Element: Comparable { ... } func max<S: NonEmptySequence>(_ sequence: S) -> S.Element where S.Element: Comparable { ... } let a: [Int] = [2, 3, 5] max(a) // Optional(5) let b: NonEmptyArray<Int> = [2, 3, 5] max(b) // 5
1:58 AM
maxmin で non optional になるのはうれしいなぁ。
Avatar
あと、そもそもappendはArray自体のmutable funcで、
2:03 AM
mutable funcで型を書き換えるのは厳しい
2:03 AM
そもそもそれで複雑性が増すよりも適切にIUO使う方が良いと思いますね
Avatar
omochimetaru 8/16/2018 2:04 AM
Array自体にemptyかnon emptyかを表す型パラメータがついたphantom typeになるような状態だと思う
Avatar
型は書き換わらないでしょ
Avatar
omochimetaru 8/16/2018 2:04 AM
それにしたってmutating funcじゃ無理だね (edited)
Avatar
var a=[] if foo a.append(1) これで終わる
2:05 AM
appendedみたいにやるなら良いかもしれない
2:06 AM
でもやっぱり複雑性マシマシで嬉しい事が少しあっても、それ以上に辛い場面が増えると思います
2:12 AM
証明系の言語で、型に値を入れ込むことが出来るなら、アリだと思いますが、現状のswiftの型システムにはマッチしなさそうかなという感じ
Avatar
あと、そもそもappendはArray自体のmutable funcで、 mutable funcで型を書き換えるのは厳しい
これは型は変わらないと思ってます。
2:12 AM
Int?42 を代入しても Int にならないのと同じで、 empty になれる型かどうか。
2:12 AM
remove は問題になりそう。
2:15 AM
数値のように全プロパティ let 扱いだと簡単だけど( RealNumberNonNegativeRealNumber だったら func -(lhs: NonNegativeRealNumber, rhs: NonNegativeRealNumber) -> RealNumber でいいけど)、 mutating func はちょっとややこしそうだ。
2:16 AM
現状 ArraypopLast は死なないメソッドだけど https://developer.apple.com/documentation/swift/array/1539777-poplast
2:16 AM
NonEmptyArraypopLast は Logic failure を起こすようにするしかない気が。それとも要素が一つしかないときに popLast したら nil を返す?
Avatar
実行効率も良く無さそうだなー
Avatar
popLast をなくして、 logic failure 前提の remove 系に統一もいいかも。
Avatar
omochimetaru 8/16/2018 2:17 AM
NonEmptyArrayを返すかクラッシュするものと Arrayを返すもの の2つ、別名メソッドとか。
2:18 AM
あ、removeは要素を返すのかw
Avatar
@omochimetaru うんw
😖 1
2:19 AM
remove はいいんだけど( logic failure としてクラッシュさせればいいから)
2:19 AM
現状 logic failure が起こらない pop がまずそう。
Avatar
omochimetaru 8/16/2018 2:19 AM
うーん、appendしてNonEmptyになるなら
2:19 AM
removeしてArrayにもどるほうがいいんだけどな
Avatar
append して NotEmpty にはならないでしょ
2:20 AM
関数型言語みたいにイミュータブルコレクションで append がコレクション返すならできるけど。
Avatar
omochimetaru 8/16/2018 2:20 AM
appendingとremovingか。
Avatar
参照型、イミュータブル、サブタイピング中心の世界はそれはそれでうまく機能してキレイだけど、 Swift はそのやり方はできないからうまくいかなさそう。
2:22 AM
append で non empty 保証できないというのも、参照型・イミュータブルな世界と比べて non empty 導入のメリット薄そう。
2:23 AM
そうかー。値型があればイミュータブルの代わりになると思ってたけど、更新系の操作で型を変えられるというのはイミュータブルにしかない利点なのか。
Avatar
この前の↑、やっぱりサブタイピング& Smart Cast と相性良さそう。 let array: Array<Int> = [2, 3, 5] guard !(array is NonEmptyArray<Int>) else { return } // ここでは `array` を `NonEmptyArray<Int>` として扱える
Avatar
omochimetaru 8/21/2018 6:36 AM
Swiftだとスマートキャストは無いから何かしらlet束縛するような形になりそうですね
Avatar
Smart Cast はサブタイピングと相性の良い仕組みだから、そもそも Swift に馴染まなさそう。
Avatar
omochimetaru 8/21/2018 6:39 AM
なるほど
Avatar
Smart Cast って抽象的な型で扱ってる場合にほしくなるわけだけど、 Swift だと基本的には型が定まってるから Smart Cast したいケースそのものが多くなくて、
6:41 AM
「何かしらlet束縛するような形になりそう」はそのとおりだけど、その前提があまり発生しなさそう。 (edited)
Avatar
omochimetaru 8/24/2018 2:01 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
2:02 AM
生文字列のレビュー始まった
2:02 AM
面白い仕様に着地してる
2:03 AM
生文字列の構文を追加するんじゃなくて、 既存の文字列のデリミタを変更できるようにすることで
2:04 AM
エスケープシーケンスが文字列コンテンツと一致しないようにして
2:04 AM
普通の文字列リテラルを生文字列にも使えるようにする
Avatar
↓ただの raw string じゃなくて、↓できるのおもしろいな。 #"This string has an \#(interpolated) item"# ####"This string has an \####(interpolated) item"####
2:27 AM
しかも、 multi-line string literal にも拡張されてる。 #""" a raw string containing \r\n """#
Avatar
omochimetaru 8/24/2018 2:27 AM
Lexerの実装負荷も比較的小さくできそうでオシャレだと思いました
Avatar
multi-line string literal も良かったけど、これも入るとますます文字列リテラルの使い勝手の良い言語になりそう。
2:31 AM
Example, 言葉での説明よりも、リテラルと結果を表にしてくれた方がわかりやすいのに・・・。
Avatar
omochimetaru 8/24/2018 2:32 AM
たしかに。
Avatar
omochimetaru 8/24/2018 3:58 AM
でも、一度差し戻されてるからなのか、提案書自体は頑張って書かれてるなあと思いました
👍 1
Avatar
どこに書けばいいかわからないからここに書くけど、Carthageのバグ潰したつもり    https://github.com/Carthage/Carthage/pull/2561 Carthage、Xcode 6.4との互換のコードが残されていたのだけど、無視して7以降でしか動かないようにしてしまった。Carthageのバージョンポリシーってあるんですかね? @ikesyo
Problem When I Built watchOS packages on Xcode 10 beta 6, It would be failed with following error: $ carthage update --platform watchOS --verbose --- xcodebuild: WARNING: Unable to open project fi...
Avatar
ikesyoさん体調悪いと書いていたのにコメントくれた 🙇
Avatar
@swift-4.1.3 @swift-4.0.3 let a = Int?.none let b = Int??.none print(a == b) print([a] == [b]) (edited)
Avatar
false false (edited)
Avatar
exit status: 1 with stderr:<stdin>:3:9: error: binary operator '==' cannot be applied to operands of type 'Int?' and 'Int??' print(a == b) ~ ^ ~ <stdin>:3:9: note: expected an argument list of type '(T?, T?)' print(a == b) ^ <stdin>:4:11: error: binary operator '==' cannot be applied to operands of type '[Int?]' and '[Int??]' print([a] == [b]) ~~~ ^ ~~~ <stdin>:4:11: note: overloads for '==' exist with these partially matching parameter lists: (Any.Type?, Any.Type?), ((), ()), (Bool, Bool), (Character, Character), (Character.UnicodeScalarView.Index, Character.UnicodeScalarView.Index), (CodingUserInfoKey, CodingUserInfoKey), (OpaquePointer, OpaquePointer), (AnyHashable, AnyHashable), (UInt8, UInt8), (Int8, Int8), (UInt16, UInt16), (Int16, Int16), (UInt32, UInt32), (Int32, Int32), (UInt64, UInt64), (Int64, Int64), (UInt, UInt), (Int, Int), (AnyKeyPath, AnyKeyPath), (Unicode.Scalar, Unicode.Scalar), (ObjectIdentifier, ObjectIdentifier), (String, String), (String.Index, String.Index), (UnsafeMutableRawPointer, UnsafeMutableRawPointer), (UnsafeRawPointer, UnsafeRawPointer), (UnicodeDecodingResult, UnicodeDecodingResult), (_SwiftNSOperatingSystemVersion, _SwiftNSOperatingSystemVersion), (AnyIndex, AnyIndex), (ContiguousArray<Element>, ContiguousArray<Element>), (ArraySlice<Element>, ArraySlice<Element>), (Array<Element>, Array<Element>), (T, T), (T?, T?), (T?, _OptionalNilComparisonType), (_OptionalNilComparisonType, T?), ((A, B), (A, B)), ((A, B, C), (A, B, C)), ((A, B, C, D), (A, B, C, D)), ((A, B, C, D, E), (A, B, C, D, E)), ((A, B, C, D, E, F), (A, B, C, D, E, F)), (ClosedRangeIndex<Bound>, ClosedRangeIndex<Bound>), (LazyDropWhileIndex<Base>, LazyDropWhileIndex<Base>), (EmptyCollection<Element>, EmptyCollection<Element>), (Self, Self), (FlattenCollectionIndex<BaseElements>, FlattenCollectionIndex<BaseElements>), (FlattenBidirectionalCollectionIndex<BaseElements>, FlattenBidirectionalCollectionIndex<BaseElements>), (Set<Element>, Set<Elemen (edited)
Avatar
ンゴゴゴ
12:09 PM
これいつの間にか治ってますね
Avatar
norio_nomura 8/30/2018 5:37 AM
SwiftSyntax has been moved to its own repo as a SwiftPM package! Check it out here: https://t.co/hpqUec0qR5
Avatar
omochimetaru 8/30/2018 5:37 AM
5:38 AM
あれ?
5:38 AM
でもこれStdlibにも含まれてますよね
5:38 AM
update-checkoutに追加されたのかな
5:39 AM
This PR sets up the infrastructure to build SwiftSyntax from its own repository for the swift-4.2-branch. For this it does: Add the new swift-syntax repository to update-checkout Add a build-scrip...
5:40 AM
やっぱりbuild-scriptも更新されるんですね
5:41 AM
This PR sets up the infrastructure to build SwiftSyntax from its own repository. For this it does: Add the new swift-syntax repository to update-checkout Add a build-script option to build and tes...
5:41 AM
引っ越して削除するPRはこっちか (edited)
Avatar
norio_nomura 8/30/2018 5:47 AM
apple/swiftのディレクトリと隣り合ってないとビルドできないみたい。 (edited)
Avatar
norio_nomura 8/30/2018 6:05 AM
gybの処理に必要なだけで、生成後は単体でビルド可能だった。
6:05 AM
テストはmacOSでしか通らないみたい。 (edited)
Avatar
norio_nomura 9/2/2018 5:15 AM
https://github.com/apple/swift-evolution/blob/master/proposals/0204-add-last-methods.mdThe name changes to index(of:) and index(where:) are easily migratable, and will be deprecated in Swift 4.2 before being removed in Swift 5. って書かれてるけど、Swift 4.2ではindex(of:)index(where:)のどちらもdeprecatedになってなくて、5.0でdeprecatedなのね。 https://github.com/apple/swift/commit/e8b6091755fc87241341e82845a29043361e8e9f
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
This should have been done for Swift 4.2 according to SE-0204, but better later than never. Deprecating these methods as of Swift 5.0. Also modfying the tests to check for the deprecation messa...
5:56 AM
Hello Evolution, I've been working on implementing Default Implementation in Protocols and I have a working early implementation of the feature. Current Implementation: https://github.com/apple/swift/pull/19116 Refer to: https://github.com/apple/swift/blob/master/docs/Gene...
5:56 AM
protocol本体にデフォルト実装かけるようにする話
Avatar
オッ
Avatar
omochimetaru 9/4/2018 5:57 AM
Azoyって乱数まわりやってる17歳じゃなかったっけ
5:57 AM
ドラゴンボールだったのが実写になっておる
Avatar
omochimetaru 9/6/2018 9:01 AM
In Swift, although we try to provide a sound, total type system as the default environment for the most part, we provide reasonably easy explicit ways to poke holes where the type system isn't a perfect fit, such as ! for unwrapping optionals known to never be nil, as! for ca...
9:02 AM
SlavaのPitch、 required initのオーバーライドをサボって required! initって書けるようにしようぜ、とのこと。 利用例 init(coder: Coder)
Avatar
親クラス側で required! init って書くと、派生クラス側でサボれるってことなんですね。個人的にはなんか変な気がする。
Avatar
omochimetaru 9/7/2018 3:39 AM
従来も、Xcodeで自動補完されて、 fatalErrorするものが吐かれていたので、 それの略記とも考えられます
Avatar
サボる側に書くのならいいと思ったんですけどね。親クラス側でサボっていいよってやってると、サボる気のない派生クラスの方で忘れる可能性が。
Avatar
omochimetaru 9/7/2018 3:41 AM
protocol FantasyCoding { init(coder: FantasyCoder) } class FantasyView: FantasyCoding { required! init(coder: FantasyCoder) { } } class MyView: FantasyView { var x, y, z: Int // ok not to override init(coder:) here } extension FantasyURL: ExpressibleByStringLiteral { // OK to add a required! initializer in an extension required! init(stringLiteral: String) { .. } }
3:41 AM
required! を書くのはサブクラス側ですよ。
Avatar
ん? FantasyView が親ですよね?
Avatar
omochimetaru 9/7/2018 3:43 AM
init(coder: ) は FantasyCoding で要求されているので
3:43 AM
FantasyView でサボっていて
3:43 AM
MyViewは孫だから、サボりを受け継ぐ。
Avatar
あ、FantasyViewではサボらず、MyViewでサボれるのかと思ってた。ちょっと読み直してみます。
Avatar
omochimetaru 9/7/2018 3:44 AM
MyView <- FantasyView (required! ) <- FantasyCoding 親子どちらでもあるので話が混ざってしまった。
3:49 AM
ひろんさんの言ってる事も正しいですねえ。
3:50 AM
通常なら孫にもrequired initの実装が伝搬するけど
3:50 AM
required! すると、そこで止まるんだ。
Avatar
うん、だから、UIViewのinit(coder:)をこれにしたいってとこだと思うんですよね。モチベーション的には。(お昼誘われたのでちょい退出。またあとで)
Avatar
omochimetaru 9/7/2018 3:53 AM
あ、各自が自分のサブビューでやるんじゃなくて、UIViewをそもそもこれにしてしまうのか、その発想は無かった。僕も読み直してきます。
Avatar
うん、やっぱり required! init には { ... } となってて処理が書けるから、その時点ではサボりはしないで、特に必要のないサブクラスでサボることを許容するんだと思います。で、そうすると、個人的にやっぱりイヤ。
Avatar
@hironytic たしかにそれだと微妙そうですね。明示的に楽にサボれるのならいいんですが・・・。 Equatable 自動生成とかみたいな。 (edited)
4:35 AM
まだ Pitch のようなので、是非 forum でご意見を🙃
🙃 1
Avatar
ぼくには個人的にヤだなという感情しか浮かばなくて、なぜイヤなのかを言語化できてなかったけど、forumでcukrさんがバッチリ言語化してくれてた 🙂 https://forums.swift.org/t/un-requiring-required-initializers/15815/5
I'm not a fan of this pitch. If I subclass UIView I would like to be reminded by a compiler that I am supposed to provide that init. Notice that every hole-poking tool you mentioned is used in the place that doesn't fit. ! for unwrapping optionals is used when you are sure ...
😀 1
Avatar
norio_nomura 9/12/2018 5:09 AM
zip()のパラメータ、a,b,tどれか一つだけ@escapingが無くても良い。 @swift-4.1.3 @swift-4.2.4 func zip<A,B,T>( _ a: @escaping ((A) throws -> T) throws -> T, _ b: @escaping ((B) throws -> T) throws -> T, _ t: @escaping (A, B) throws -> T ) rethrows -> T { return try a() { _a in return try b() { _b in return try t(_a, _b) } } } let xs = ["x", "s"] let ys = ["y", "s"] let totalByteCount = try zip(xs.withUnsafeBytes, ys.withUnsafeBytes) { x, y in x.count + y.count } print(totalByteCount) // "64\n" (edited)
Avatar
96 (edited)
Avatar
norio_nomura 9/12/2018 5:12 AM
どの@escapingが無くても良い。
Avatar
64
Avatar
norio_nomura 9/12/2018 5:15 AM
4.1と4.2で結果が違うのか。
Avatar
新しいバグを見つけた気がする
11:11 AM
structをobjcに一回投げて_SwiftValueにすると、_SwiftValue -> ExistentialへのCastがFailする
11:11 AM
@swift-4.1.3 import Foundation protocol Animal {} struct Cat: Animal {} print((Cat() as! AnyObject) as? Animal) print((Cat() as! AnyObject) as? Cat) (edited)
Avatar
exit status: 134 with stderr:<stdin>:4:7: warning: expression implicitly coerced from 'Animal?' to Any print((Cat() as! AnyObject) as? Animal) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <stdin>:4:29: note: provide a default value to avoid this warning print((Cat() as! AnyObject) as? Animal) ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~ ?? <#default value#> <stdin>:4:29: note: force-unwrap the value to avoid this warning print((Cat() as! AnyObject) as? Animal) ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~ ! <stdin>:4:29: note: explicitly cast to Any with 'as Any' to silence this warning print((Cat() as! AnyObject) as? Animal) ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~ as Any <stdin>:5:7: warning: expression implicitly coerced from 'Cat?' to Any print((Cat() as! AnyObject) as? Cat) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <stdin>:5:29: note: provide a default value to avoid this warning print((Cat() as! AnyObject) as? Cat) ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~ ?? <#default value#> <stdin>:5:29: note: force-unwrap the value to avoid this warning print((Cat() as! AnyObject) as? Cat) ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~ ! <stdin>:5:29: note: explicitly cast to Any with 'as Any' to silence this warning print((Cat() as! AnyObject) as? Cat) ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~ as Any Could not cast value of type 'main.Cat' (0x7fe4e571b100) to 'Swift.AnyObject' (0x7fe4e03ad260). #0 0x0000000003f25074 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x3f25074) #1 0x0000000003f253b6 SignalHandler(int) (/usr/bin/swift+0x3f253b6) #2 0x00007fe4e52eb390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #3 0x00007fe4e3a2a428 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35428) #4 0x00007fe4e3a2c02a abort (/lib/x86_64-linux-gnu/libc.so.6+0x3702a) #5 0x00007fe4e0288fd3 (/usr/li (edited)
Avatar
AnyObjectのキャストがLinuxだとあれか
Avatar
omochimetaru 9/18/2018 3:26 AM
https://developer.apple.com/jp/xcode/
新しいコードを追加すると、追加した行のみ再コンパイルされます。
最近コンパイラに、部分指定してパースとかがちょこちょこ追加されていたんだけど、↑これってその成果なのかな
Xcodeには、iPhone、iPad、Mac、Apple Watch、Apple TV向けの優れたアプリケーションを作成するために必要なあらゆる機能が用意されています。
Avatar
koher05/07/2018 この前 @Taketo Sano さんが困ってた自作型の Conditional Conformance & Codable 自動生成はできるようになりそうですね。
これかなり便利ですね😙
Avatar
新しいコードを追加すると、追加した行のみ再コンパイルされます。
この件は、Xcode Playground の話なので、たぶん違いますね。 最近の on demand parsing は、インクリメンタルビルドにおいての高速化のためです。
Avatar
omochimetaru 9/18/2018 6:27 AM
Playgroundで追加した行だけ再コンパイルするのは、元からあったREPLの仕組みの方ってことですか?
Avatar
Xcode 10 で Playground で逐次実行ができるようになったので、それの事だと思います。
Avatar
omochimetaru 9/18/2018 6:29 AM
あ〜
6:32 AM
Discover major advancements in Xcode playgrounds. Learn advanced tips and techniques, hear about new and often overlooked workflows, and...
6:32 AM
再生ボタンみたいなやつが出てくれないなあ
Avatar
omochimetaru 9/18/2018 6:33 AM
新規playgroundだと出るな。
6:33 AM
6:33 AM
いや、そのメニューが出ない
Avatar
▼が無いですか?
Avatar
omochimetaru 9/18/2018 6:34 AM
▼はあるけど、ポップアップメニューが出ないです
Avatar
長押しででません?
Avatar
omochimetaru 9/18/2018 6:35 AM
新規作成したplaygroundは、ステップ実行する○→は機能しました。
6:35 AM
長押しで出た・・・!!!!
6:35 AM
おー、前からあるやつでも、いけました。ありがとうございます。
6:36 AM
なんで長押し・・・
6:38 AM
Comparison / Authors / Log のボタンも同じコンポーネントですね、すでにボタンが凹んでるときは短クリックでポップアップが出るから、気づいていなかった。
Avatar
結構Appleの、ボタンの横にちっちゃい▼ついてるのは長押し意味してるのがそこら中にあるよ
Avatar
omochimetaru 9/18/2018 7:12 AM
知らなかった・・・
7:12 AM
なんか押しにくいって感じてる事があったのはそういうことか
Avatar
XcodeのRun/Buildとかもそうじゃないかな、Instrumentをそこから出せるはず
Avatar
omochimetaru 9/18/2018 7:14 AM
ほんとだ〜〜〜〜〜〜
7:14 AM
これは長押ししないとほんとうに押し込んじゃうね
7:14 AM
全く気づいてなかった
Avatar
OptionSetってHashableになってても良い気がしているんですがなってないんですね
7:05 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
7:05 AM
昨日気付いた
7:05 AM
どうなんだろう
Avatar
RawValue に何も制限設けてないのでむずかしいんじゃないかな。 extension OptionSet : Hashable where RawValue: Hashable は標準であってもいい気はしますが、 普通の OptionSetvar rawValue: RawValue しか持っていないので RawValue == UInt8 とかなら struct MyOptions : OptionSet, Hashable って宣言するだけで Hashable に準拠できるので、敢えて追加するモチベーションは低くなりそう。 (edited)
Avatar
omochimetaru 9/20/2018 7:42 AM
RawRepresentableって
7:42 AM
自前のプロパティの追加って禁止されるんでしたっけ。
Avatar
そんなことないですが、 init(rawValue:) でコンストラクトできる必要があるので、他のプロパティが 同値性に影響を与えるのは不自然でしょうね。
Avatar
omochimetaru 9/20/2018 7:44 AM
なるほど
7:45 AM
そもそも SetAlgebra.Element : Equatable がついてて、 OptionSet だと Element == Self なので、Equatableは要請されているのか
7:47 AM
Hashableに限らず、すべてのプロトコルに関して、 RawRepresentable.RawValue が conform してるプロトコルは、本来的に Self も conform できるはず って話と かといって、特にHashable をOptionSetにおいて特別視する理由がない と思った。
Avatar
一応 SetAlgebra 自体 Equatable 要求ありますよ。
Avatar
omochimetaru 9/20/2018 7:47 AM
あ、ほんとだ。
7:49 AM
SetAlgebraの実装においては、ElementがHashableのほうが、内部実装をハッシュテーブルにできて有利、みたいな話は別途ありそうだけど・・・
Avatar
OptionSet.Element == Self は標準ではあるけど、要求ではないです。
Avatar
omochimetaru 9/20/2018 7:50 AM
あーこれはassociatedtypeのデフォルト値か。
7:51 AM
/// The element type of the option set. /// /// To inherit all the default implementations from the `OptionSet` protocol, /// the `Element` type must be `Self`, the default. associatedtype Element = Self (edited)
7:53 AM
このコメントの must be はどういう意味です?
Avatar
https://github.com/apple/swift/blob/7c56af08a719ebd50955c556b4a76ec2d4dc8f13/stdlib/public/core/OptionSet.swift#L199 この実装を継承するためには、 Element == Self でなければならない。
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 9/20/2018 7:55 AM
なるほど。特にmust beじゃ無さそう・・・
Avatar
extension Set: RawRepresentable where Element == Int { public typealias RawValue = Set<Int> public var rawValue: Set<Int> { return self } public init(rawValue: Set<Int>) { self = rawValue } } extension Set : OptionSet where Element == Int {} むりやりだけど、 Element == Self じゃない例。
Avatar
RawValue に何も制限設けてないのでむずかしいんじゃないかな
8:02 AM
なるほど
8:03 AM
ちゃんと読んでなかったけどOptionSet、UIntの場合はHashableで良さそうなのにHashableになってなかったからなんでだー、みたいな気持ちでした
8:03 AM
OptionSet.Element取れるなら確かに難しそう
Avatar
@ikesyo iOSDCの時に教えてもらったcarthage-verify試してみてPR送ってみました 🙏 https://github.com/Carthage/Carthage/pull/2585
Motivation & Context I want to use carthage-verify on workflows to skip duplicated builds. However, current .Package.version file doesn't contains Xcode version information. So we can't...
10:36 AM
#carthage ほしくなってきた
Avatar
作った
Avatar
最高
Avatar
ソート位置はスマホからいじれんので後で直します
Avatar
protocol extensionよりもextensionの実装が優先されるのって仕様ですか? 不定だけど動作上今は優先されているだけですか?
Avatar
@swiftbot protocol Proto { func test() } extension Proto { func test() { print("Proto") } } struct Impl: Proto { func test() { print("Impl") } } let a = Impl() a.test() こういうやつですか?
🛠 1
Avatar
swiftbot BOT 9/25/2018 5:57 AM
Author icon
t.ae
protocol Proto { func test() } extension Proto { func test() { print("Proto") } } struct Impl: Proto { func test() { print("Impl") } } let a = Impl() a.test()
Version:
swift-4.1.1-RELEASE
Output:
Impl
Error:
Avatar
Impl内にtest()書くのじゃなくて更にextensionに書く場合にすべきか
Avatar
ですです、これがSwiftのアップデートでProtoの方が呼ばれるようになってしまうリスクはあるのかなと
Avatar
具体型として見た場合とExistentialとして見た場合とで挙動が変わる場合がある
5:59 AM
cc @omochimetaru @Yuta Saito
Avatar
呼ばれた
Avatar
1. protocolのrequireとしてfuncが記述されているかどうか 2. protocolをimplしたsuperclassに実装があるかどうか
6:00 AM
この条件で挙動が変わります
6:01 AM
Documentにも明記されていない以上、いつ変わってもおかしくないと思いますね。
Avatar
requireされるとwitness tableに乗るので動的にディスパッチされるんですけど、ない場合は常に静的にディスパッチされます
Avatar
1で変わるのは仕様と思いますが、2 はとても怪しいですね
Avatar
protocolをimplしたsuperclassに実装があるかどうか
現状witness tableが作られるのはprotocolへの準拠ごとなので、クラスを継承した場合に新しいwitness tableが作られず、サブクラスのメソッドが呼ばれないやつですね
6:06 AM
サブクラスで補完が効いてしまうのが厄介
6:10 AM
サブクラスを作ったときにwitness tableを作らないのは設計上の問題なのかとか、知ってたりしますか? @omochimetaru
Avatar
omochimetaru 9/25/2018 6:11 AM
呼ばれた
Avatar
(一旦protocol extensionよりもextensionの実装が優先されるのは変わりうる可能性があるのは理解しました!、ありがとうございます)
Avatar
そこの優先関係についてはextensionのほうが優先されるのが普通じゃないかと思うんですが変更されうるんですかね
Avatar
omochimetaru 9/25/2018 6:16 AM
@Yuta Saito そこはよくわかんないっていうかiOSDCで俺が君に聞いたやつじゃんw
😷 1
😋 1
6:17 AM
でも親でwitnesstableもって子の呼び出しはvtable経由にしないと、子のインスタンスが親としてアップキャストされているときに
6:17 AM
挙動が変わっちゃうのは継承ベースOOPとしては変な感じがするから
6:17 AM
意図的な気がする
6:18 AM
最近の傾向だとドキュメントされてない怪しい挙動でも、広く使われている場合、 下位互換性を壊さないように注意される感じだから、
Avatar
そういやそうでしたねw あー、確かにキャストして挙動変わるのはまずそう。
Avatar
omochimetaru 9/25/2018 6:18 AM
将来的にも壊れないと思ってよさそうだけど
❤ 1
Avatar
protocol extensionで定義したメソッドをvtableに載せれば期待する挙動になりそうですけど、罠がありそう
Avatar
omochimetaru 9/25/2018 6:20 AM
extensionは
Avatar
vtableに乗せちゃうかfinal扱いにするか
Avatar
omochimetaru 9/25/2018 6:20 AM
パッケージの外で定義された場合の考慮が必要で (edited)
Avatar
どちらかの仕様がほしいよなぁと思う
Avatar
omochimetaru 9/25/2018 6:21 AM
vtableはクラスごとにプロセスに1つしかないから
Avatar
あー、なるほど、モジュール外でprotocol extensionが生やせるのかー。
6:24 AM
無理そう
Avatar
open classにprotocolを生やした場合に、強制的にvtable作るのはダメですかね
6:28 AM
subclassは明示的にoverride書く必要が出てきて
6:28 AM
extension overrideは4で封じられたので問題ないはず
Avatar
その場合、強制的に作られたvtableに入っているフィールドは何になりますか?
Avatar
omochimetaru 9/25/2018 6:38 AM
error: iOSGround.playground:35:10: error: overriding non-@objc declarations from extensions is not supported
6:44 AM
@tarunon パッケージX、パッケージY、パッケージZにおいて、 パッケージXにclass Animalとclass Cat : Animalが定義されていて Animalのspeakメソッドが定義されていて、Catでは特にオーバライドされていない ときに パッケージYでCatのextensionとしてspeakを実装したら、 パッケージXの中のコードでAnimalのspeakメソッドを呼び出しているところで、 そのYで与えた実装が走って欲しい って話だよね?
Avatar
extensionの中でoverrideは言語仕様として明確に禁止するべきと考えています
Avatar
omochimetaru 9/25/2018 6:45 AM
あれ、じゃあ、どういう話をしてるんだ? > open classにprotocolを生やした場合に、強制的にvtable作るのはダメですかね
Avatar
open classの定義がパッケージXにあって、パッケージYにサブクラス定義がある場合
6:47 AM
パッケージXでprotocol extensionによって実装されたfunction群をパッケージYでoverrideができないのが困る
Avatar
omochimetaru 9/25/2018 6:49 AM
// package X protocol AnimalProtocol { func a() } extension AnimalProtocol { func a() { print("X.AnimalProtocol.a") } } open class Animal : AnimalProtocol { } // package Y import X class Cat : Animal { func a() { ... } }
6:49 AM
こういう形?
Avatar
そう
6:50 AM
これがoverrideではなく、あやふやな状態になるのがね
Avatar
omochimetaru 9/25/2018 6:50 AM
あやふやじゃなくて、今だと、Cat.aの定義自体が禁止されるっぽい
Avatar
マジ?
Avatar
omochimetaru 9/25/2018 6:50 AM
error: iOSGround.playground:35:19: error: overriding non-@objc declarations from extensions is not supported
Avatar
ほほー
6:50 AM
それはそれでいいね
Avatar
omochimetaru 9/25/2018 6:50 AM
あ、ごめん、ちょっとまって。少し状態が違った
🤕 1
Avatar
あやふやな状態さえ消えれば私はなんでもいいよ
Avatar
omochimetaru 9/25/2018 6:51 AM
↑のエラーが出るのは extension Animal { } の場合だった。定義できちゃうな。
Avatar
ムッ
Avatar
なるほど言いたいことを理解した
Avatar
omochimetaru 9/25/2018 6:53 AM
@swift-4.2.4 protocol AnimalProtocol { func a() func c() } extension AnimalProtocol { func a() { print("AnimalProtocol.a") } func b() { print("AnimalProtocol.b") } func c() { print("AnimalProtocol.c") } } class Animal : AnimalProtocol { func a() { print("Animal.a") } func b() { print("Animal.b") } } class Cat : Animal { override func a() { print("Cat.a") } override func b() { print("Cat.b") } func c() { print("Cat.c") } } func invokeA<X: AnimalProtocol>(_ x: X) { x.a() } func invokeB<X: AnimalProtocol>(_ x: X) { x.b() } func invokeC<X: AnimalProtocol>(_ x: X) { x.c() } var cat1: Cat = Cat() invokeA(cat1) invokeB(cat1) invokeC(cat1)
Avatar
Cat.a AnimalProtocol.b AnimalProtocol.c
Avatar
omochimetaru 9/25/2018 6:55 AM
a: witness tableエントリあり、vtable親あり、vtable子あり、Catが呼ばれる b: witness tableエントリなし、vtable親あり、vtable子あり、AnimalProtocolが呼ばれる c: witness tableエントリあり、vtable親なし、vtable子なし、AnimalProtocolが呼ばれる
6:56 AM
tarunonが言ってるのはcのパターンだな。
6:57 AM
cのパターンにおいて、望み通り子で処理を差し替えたければ、 Animalにfuncを書いてaのパターンにするべきだけど、 protocol extensionをAnimal以外でも使ってるから、 funcを書きつつsuperみたいにprotocol extensionの実装を呼び出すことができないから、 それはやりたくない、と。
Avatar
モジュール内でrequirementを満たす必要があるので、モジュール外でprotocol extensionされる可能性を考慮しなくて良くなりそう
Avatar
omochimetaru 9/25/2018 7:06 AM
protocol AnimalProtocol { func a() func c() func d() } extension AnimalProtocol { func a() { print("AnimalProtocol.a") } func b() { print("AnimalProtocol.b") } func c() { print("AnimalProtocol.c") } func d() { defaultD(self) } } func defaultD<X: AnimalProtocol>(_ obj: X) { print("AnimalProtocol.d") } class Animal : AnimalProtocol { func a() { print("Animal.a") } func b() { print("Animal.b") } func d() { defaultD(self) } } class Cat : Animal { override func a() { print("Cat.a") } override func b() { print("Cat.b") } func c() { print("Cat.c") } override func d() { print("Cat.d") } } func invokeA<X: AnimalProtocol>(_ x: X) { x.a() } func invokeB<X: AnimalProtocol>(_ x: X) { x.b() } func invokeC<X: AnimalProtocol>(_ x: X) { x.c() } func invokeD<X: AnimalProtocol>(_ x: X) { x.d() } var cat1: Cat = Cat() invokeA(cat1) invokeB(cat1) invokeC(cat1) invokeD(cat1)
7:07 AM
Cのパターンを書き換えてAのパターンにしつつ、 デフォルト実装を使い回すために実装を外に出したのがDです。 これはまあまあ実用的なんじゃないか @tarunon
Avatar
これは実用的
Avatar
omochimetaru 9/25/2018 7:08 AM
Cの挙動についても、今の理解だと、不便なのはわかるけど、特にあやふやな点は無いと思った。
Avatar
いや
Avatar
omochimetaru 9/25/2018 7:08 AM
Catでconformしたように見えてしまうと、謎挙動に感じられる? (edited)
Avatar
(foo as Subclass).method() と (foo as Existential).method()で挙動が変わるのがよろしくない
7:09 AM
つまり実質的には
Avatar
omochimetaru 9/25/2018 7:09 AM
ああ、なるほど。
Avatar
「同名同型のオーバーロード」であるのだけど
7:09 AM
それを理解できる言語仕様でないのが問題
7:10 AM
そこが理解できるなら別にいいんじゃないのんって感じ、でも
7:10 AM
Protocolの定義にあるメソッドを、自前でConformしたつもりが
7:10 AM
できていないケースがあります、はやっぱりしんどいと思う
Avatar
omochimetaru 9/25/2018 7:10 AM
実はAnimalの時点で、用意しないでデフォルトを使う、ということが固定されてるのがわかりにくいね。
7:11 AM
conformしてるメソッドに明示的にアトリビュートをつけるっていう提案があった気がする
Avatar
1, witness tableへ乗るImpl 2, vtableへ乗るimpl 3, 同名同型のoverloadになるimpl(罠) (edited)
7:11 AM
このうち
Avatar
omochimetaru 9/25/2018 7:11 AM
@_implements ってそれなのかな
Avatar
2はoverride明記だからいいけど、1,3が区別つかないのがやばい
7:12 AM
3を言語仕様的に存在を許さないようにするのが一番いいと思うのだけど
7:12 AM
手段は問わない、コンパイルエラーにしてもいいし、強制的に2に乗るようにしてもいい
Avatar
omochimetaru 9/25/2018 7:13 AM
コンパイルエラーはできそうだね
7:13 AM
現状で静的にわかるしエラーにする分には面倒な事は減る
7:16 AM
@_implements は別名メソッドでconformする謎の機能だった。
Avatar
↑の話を追えてないけど、
同名同型のoverloadになるimpl(罠)
に関しては vtable 関係なく↓とかもありませんか? @swiftbot protocol P {} extension P { func foo() -> String { return "P" } } struct S: P { func foo() -> String { return "S" } } let s: S = S() let p: P = s print(s.foo()) print(p.foo())
🛠 1
Avatar
swiftbot BOT 9/25/2018 7:29 AM
Author icon
koher
protocol P {} extension P { func foo() -> String { return "P" } } struct S: P { func foo() -> String { return "S" } } let s: S = S() let p: P = s print(s.foo()) print(p.foo())
Version:
swift-4.1.1-RELEASE
Output:
S P
Error:
Avatar
これはwitness tableが絡んでないので幾分かマシです
7:30 AM
witness tableがある状態で似たようなことが起きるのが問題で、殊これに関してはただの静的呼び出しなので問題はなさそう
Avatar
なるほど、↑ちゃんと読んでみます。 (edited)
Avatar
もちろん、それが理解できる言語仕様の方が良いなあとは思います
7:32 AM
Protocolに適合する実装のときにアノテーション明記するの方が実はいいんじゃないかなと思い始めた
Avatar
omochimetaru 9/25/2018 7:32 AM
慣れちゃったけど多分よくないよなあ・・・
7:32 AM
わかんないよなあ
Avatar
↓のような話をしてるのか。 @swift-4.2.4 protocol P { func foo() -> String } extension P { func foo() -> String { return "P" } } class C: P { } class SC: C { func foo() -> String { return "SC" } } let sc: SC = SC() let c: C = sc let p: P = c print(sc.foo()) print(c.foo()) print(p.foo())
Avatar
SC P P
Avatar
@swift-4.2.4 protocol P { func foo() -> String } extension P { func foo() -> String { return "P" } } class C: P { func foo() -> String { return "C" } } class SC: C { override func foo() -> String { return "SC" } } let sc: SC = SC() let c: C = sc let p: P = c print(sc.foo()) print(c.foo()) print(p.foo())
Avatar
SC SC SC
Avatar
omochimetaru 9/25/2018 8:03 AM
https://twitter.com/omochimetaru/status/1044497430643798016 まとめました @noppe @tarunon @Yuta Saito
Discordに出てきた話をまとめた > Swiftで継承とプロトコルとprotocol extensionが絡んだ時のメソッド呼び出し https://t.co/3kxEDqVQaX
Avatar
@koher Override書いてる時は普通なのです。問題がない。
Avatar
1つ目の override がない場合の挙動の話ですよね?
Avatar
desudesu
Avatar
↓の useP が specialize されてもインライン展開されても P が表示されるのか。まさに「同名同型のoverloadになるimpl(罠)」だ・・・。 protocol P { func foo() -> String } extension P { func foo() -> String { return "P" } } class C: P { } class SC: C { func foo() -> String { return "SC" } } func useP<T: P>(_ p: T) { print(p.foo()) } func useSC(_ sc: SC) { print(sc.foo()) } let sc: SC = SC() useP(sc) // P useSC(sc) // SC
Avatar
常識的に考えると同名同型のoverloadなんて存在しないですからね、無意識のうちに候補から外してしまう
8:34 AM
例えばoverloadは関数にあるという先入観があるだけで、変数についても同様にoverloadが存在しうることを失念してしまいます。 (edited)
Avatar
これって foo が同名で同じ型でオーバーロードされてるというわけじゃないんですか? p.foosc.foo と別のメソッドを示しているわけではなく?
Avatar
sc.foo()がprotocol extensionのfoo()に対して、事実上overrideではなくoverloadになっている (edited)
Avatar
この「仕様」の理由としては、 「親クラスの extension 上の decl は override できないのと同様に」ということらしいのですが、それなら警告なりエラーなり出すべきだというのは同意です。
11:04 AM
class Base {} extension Base { func foo() {} } class Derived : Base { override func foo() {} // error: overriding non-@objc declarations from extensions is not supported }
Avatar
モジュールの外でextensionされる可能性があるから、エラーにはできなさそうな気が 🤔
Avatar
@tarunon 変数についてのoverloadというのがよくわからず。
Avatar
struct A { var url: String } 通常変数はoverloadはできないのですが、protocol extensionを使えばこのAにURL型の変数を生やすことが可能です
Avatar
This post describes the goals, release process, and estimated schedule for Swift 5.0.
swift 5
Avatar
omochimetaru 9/26/2018 1:38 AM
November 16, 2018 (final branching)
1:38 AM
意外とハヤイ
Avatar
final branching までに async/await はまとまりそうにないなぁ。 (edited)
😢 2
1:44 AM
↓このあたりも気になるところ。 https://forums.swift.org/t/opaque-result-types/15645
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. EDIT: The proposal has been significantly revised since this initial posting. The most up-to-date ...
Avatar
omochimetaru 9/26/2018 1:46 AM
CondConfやEquatable自動生成が4.1で来たみたいに、 asyncは5.1の目玉になりそう
Avatar
↓これ終わらなかったら辛い。 https://github.com/apple/swift/pull/16980
This proposal introduces the @dynamicCallable attribute, which enables nominal types to be "callable" via a simple syntactic sugar. This is the implementation of the Swift evolution propo...
Avatar
asyncレベルの変更を...と思ったけどcondconfはデカかった
Avatar
確かに cond conf の前例があるから、 5.1 で async/await もワンチャンあるな。
Avatar
omochimetaru 9/26/2018 1:47 AM
そうだdynCallまだかw
Avatar
condconf入ってないのに先行してcodable出ちゃった前例もあるから
Avatar
この PR のスレッド、ずーっとやりとりしてる。 < @dynamicCallable (edited)
Avatar
型落ちasyncがはみ出してくる可能性もありそう
Avatar
型落ち async って何ですか?
Avatar
omochimetaru 9/26/2018 1:48 AM
modifyアクセサがそれな気がしてる
Avatar
フル機能揃ってなくてとりあえず出しだけみたいな
Avatar
omochimetaru 9/26/2018 1:48 AM
下請けがコルーチンだし。
Avatar
actor とかいつになることやら・・・。
Avatar
omochimetaru 9/26/2018 1:48 AM
非同期には使えないが。
Avatar
cancel出来ないasyncだけこんにちはみたいな展開もあり得る
1:49 AM
ないかw
Avatar
「同名同型のoverloadになるimpl(罠)」と「通常変数はoverloadはできないのですが、protocol extensionを使えばこのAにURL型の変数を生やすことが可能です」をあわせると↓みたいになるのか。 @swift-4.2.4 protocol P { var a: Int { get } } extension P { var a: Int { return 1 } } class C: P {} class SC: C { var a: Int = 2 } let sc: SC = SC() let c: C = sc print(sc.a) print(c.a)
Avatar
2 1
Avatar
そうですねw
2:04 AM
これを利用してMockingできないかと考えたことがありましたが、ヤバすぎたのでやめました
2:04 AM
犯罪に近い
Avatar
それはヤバそう😅
Avatar
結局sharedをやめて素直にinitの引数に入れるのが一番良かった
Avatar
Kishikawa Katsumi 9/26/2018 3:36 AM
Swift 4.2のマイグレータが追加するDictionaryの型を変換するヘルパーメソッドはセンスがイマイチ。結局全部消した。
Avatar
@swift-4.2.4 var iterator = [].enumerated().makeIterator() iterator.next()
Avatar
stderr:<stdin>:2:10: warning: result of call to 'next()' is unused iterator.next() ^ ~~
Avatar
@swift-4.1.3 var iterator = [].enumerated().makeIterator() iterator.next()
Avatar
stderr:<stdin>:2:10: warning: result of call to 'next()' is unused iterator.next() ^ ~~
Avatar
Xcodeの最新betaまだ見てないんですが、👆のコードをXcode 10.0 (10A255)のPlaygroundで書いたら コンソールにこんなの出ました
SWIFT RUNTIME BUG: unable to demangle type of field '_position'. mangled type name is '5IndexSlQz'
Avatar
@swift-4.2.4 let l = (0...40).lazy.filter({ _ in true }) Mirror(reflecting: l).children.forEach { print($0) }
Avatar
(label: Optional("_base"), value: ClosedRange(0...40)) (label: Optional("_predicate"), value: ())stderr:warning: the Swift runtime was unable to demangle the type of field '_predicate'. the mangled type name is 'Sb7ElementSTQzc'. this field will show up as an empty tuple in Mirrors
Avatar
お、でてきた
Avatar
花芽尋かすみ 9/28/2018 2:04 PM
@swift-4.2.4 [1, 2, 3].forEach { print($0) }
Avatar
1 2 3
😲 1
Avatar
let num = 10 let other = 12 // 🤔 網羅的に書けないし、くどいし、ロジックに不安がある if num < other { print("small") } else if num > other { print("great") } else { print("same") } こういう「<, ==, > それぞれのケースを網羅的に処理する」コードってどうやって書いてますか? import Foundation // 代替案1 extension Comparable { func comparisonResult(with other: Self) -> ComparisonResult { if self < other { return .orderedAscending } if self > other { return .orderedDescending } return .orderedSame } } // 🤔 網羅的なのはいいけど、非直感的… // asc, desc のどっちがどっちなのかいつも思考が止まる[IMO] switch num.comparisonResult(with: other) { case .orderedAscending: print("small") case .orderedSame: print("same") case .orderedDescending: print("great") } // 代替案2 // 新しいenumが欲しい enum Comparison { case greater, same, smaller } extension Comparable { func comparison(with other: Self) -> Comparison { if self < other { return .smaller } if self > other { return .greater } return .same } } // 👍 網羅的!直感的! switch num.comparison(with: other) { case .smaller: print("small") case .same: print("same") case .greater: print("great") } #swift-contrib に持っていきたいやつかなと思ったけど、 (ちゃんと読んでないですが)突き詰めるとComparableの設計そのものの話になってめんどくさそう…? https://forums.swift.org/t/proposal-formalized-ordering-take-2/3540 https://forums.swift.org/t/pitch-comparison-reform/5662/6 (edited)
Since we're running short on time, and the previous discussion thread diverged, here's my attempt to fix the Comparable protocol. Pull request: https://github.com/apple/swift-evolution/pull/464 TL;DR: 1. Equatable remains unchanged, while Comparable bloats a bit to support...
Getting this sorted out is definitely a worthwhile effort. I do have thoughts about this proposal: I continue to have reservations about an identical spelling (e.g. ==) giving two different answers with the same values of the same type, depending on the generic context....
Avatar
@takasek .less, .equal, .greater が良いように思います。
2:06 PM
ところで、 @swift-4.2.4 let a = 42.0 let b = 0.0 / 0.0 if a < b { print("a < b") } else if a > b { print("a > b") } else if a == b { print("a == b") } else { print("😇") }
😇 2
Avatar
😇
Avatar
なるほど、 .less !
2:21 PM
@swift-4.2.4 import Foundation let c = NSNumber(value: Double(42)) let d = NSNumber(value: Double.nan) switch c.compare(d) { case .orderedAscending: print("asc") case .orderedSame: print("same") case .orderedDescending: print("desc") }
Avatar
desc
Avatar
@takasek 元の話については、僕は特に↓で問題を感じてないですね。 // 🤔 網羅的に書けないし、くどいし、ロジックに不安がある if num < other { print("small") } else if num > other { print("great") } else { print("same") }
Avatar
Perl とかにある宇宙船演算子もいいかも。 @swift-4.2.4 infix operator <=> enum Comparison { case less case equal case greater } func <=> <T: Comparable>(lhs: T, rhs: T) -> Comparison { if lhs < rhs { return .less } else if lhs > rhs { return .greater } else { return .equal } } let a = 2 let b = 3 switch a <=> b { case .less: print("a < b") case .equal: print("a == b") case .greater: print("a > b") } (edited)
Avatar
a < b (edited)
Avatar
Kishikawa Katsumi 10/1/2018 8:03 AM
class SomeViewController: UIViewController { ... override func viewDidLoad() { super.viewDidLoad() ... var parameters = SomeStruct() { didSet { someMethod(parameters: parameters) } } ... ^ これは循環参照ですよね?
Avatar
omochimetaru 10/1/2018 8:04 AM
あれ?それコンパイル通りますか?
8:04 AM
代入文の左辺値を右辺値でキャプチャできなかったような?
8:04 AM
あ、読み間違えた。
Avatar
Kishikawa Katsumi 10/1/2018 8:05 AM
これの循環を切る場合は、 class SomeViewController: UIViewController { ... override func viewDidLoad() { super.viewDidLoad() ... var someClosure: () -> Void = {} var parameters = SomeStruct() { didSet { someClosure() } } someClosure = { [weak self] in self?.someMethod(parameters: parameters) } ...
8:05 AM
こんな感じでsomeClosure()で包む、以外にスマートな方法ありますか?
8:06 AM
元のコードを書き換えるときにミスってるかもしれないので良くわからない場合は言ってもらえればコンパイルできるやつを書きます。
Avatar
omochimetaru 10/1/2018 8:11 AM
確認ですけどviewDidLoadのローカルスコープでcomputed propertyを定義してるんですよね?(インスタンスのプロパティではなく
Avatar
Kishikawa Katsumi 10/1/2018 8:13 AM
viewDidLoadのローカルスコープで、ローカル変数を定義しています。 override func viewDidLoad() { var parameters = SomeStruct() ... }
8:14 AM
^ これが override func viewDidLoad() { var parameters = SomeStruct() { didSet { someMethod(parameters: parameters) } } ... }
8:14 AM
^ こうです。
Avatar
omochimetaru 10/1/2018 8:19 AM
@swiftbot struct Stone {} class Cat { init() { print("init cat") } deinit { print("deinit cat") } func nya() { print("begin nya") var stone = Stone() { didSet { self.mofu(stone) } } stone = Stone() print("end nya") } func mofu(_ stone: Stone) { print("mofu") } } func main() { var cat = Cat() cat.nya() } main()
🛠 1
Avatar
swiftbot BOT 10/1/2018 8:19 AM
Author icon
omochimetaru
struct Stone {} class Cat { init() { print("init cat") } deinit { print("deinit cat") } func nya() { print("begin nya") var stone = Stone() { didSet { self.mofu(stone) } } stone = Stone() print("end nya") } func mofu(_ stone: Stone) { print("mofu") } } func main() { var cat = Cat() cat.nya() } main()
Version:
swift-4.1.1-RELEASE
Output:
init cat begin nya mofu end nya deinit cat
Error:
/usercode/main.swift:32:9: warning: variable 'cat' was never mutated; consider changing to 'let' constant var cat = Cat() ~~~ ^ let
Avatar
omochimetaru 10/1/2018 8:20 AM
@Kishikawa Katsumi didSetのコードブロックはselfをキャプチャしないので最初のコードでも循環してないと思います。↑に試してみたけど、deinitが呼ばれています。
Avatar
Kishikawa Katsumi 10/1/2018 8:22 AM
お、ありがとうございます。じゃあ他のコードが影響しているのかな。あとで再現できるプロジェクトの形にしてみます。 🙇
👀 1
Avatar
Kishikawa Katsumi 10/1/2018 3:31 PM
@swiftbot struct Stone {} struct Wall { var onChanged: () -> Void = {} } class Cat { var wall = Wall() init() { print("init cat") } deinit { print("deinit cat") } func nya() { print("begin nya") var stone = Stone() { didSet { self.mofu(stone) } } wall.onChanged = { print(stone) } print("end nya") } func mofu(_ stone: Stone) { print("mofu") } } func main() { let cat = Cat() cat.nya() } main()
🛠 1
Avatar
swiftbot BOT 10/1/2018 3:31 PM
Author icon
kishikawakatsumi
struct Stone {} struct Wall { var onChanged: () -> Void = {} } class Cat { var wall = Wall() init() { print("init cat") } deinit { print("deinit cat") } func nya() { print("begin nya") var stone = Stone() { didSet { self.mofu(stone) } } wall.onChanged = { print(stone) } print("end nya") } func mofu(_ stone: Stone) { print("mofu") } } func main() { let cat = Cat() cat.nya() } main()
Version:
swift-4.1.1-RELEASE
Output:
init cat begin nya end nya
Error:
Avatar
Kishikawa Katsumi 10/1/2018 3:33 PM
@omochimetaru 直接の原因?はexcapedなクロージャがあって(上ではonChanged)それがstoneをキャプチャしてるとCatが解放されないというものでした。
3:34 PM
ただ、これでCatが解放されないのがイマイチわからない。
Avatar
omochimetaru 10/1/2018 3:47 PM
@swiftbot class Cat { init() { print("init cat") } deinit { print("deinit cat") } func nya() -> () -> Void { print("begin nya") var stone = Int(2) { didSet { // (1) print("set stone") // (2) // print("set stone, \(self)") } } print("end nya") return { print(stone) } } } func main() { var cap: (() -> Void)? = nil do { print("---1---") let cat = Cat() print("---2---") cap = cat.nya() } // end of `cat` print("---3---") cap = nil print("---4---") } main()
🛠 1
Avatar
swiftbot BOT 10/1/2018 3:47 PM
Author icon
omochimetaru
class Cat { init() { print("init cat") } deinit { print("deinit cat") } func nya() -> () -> Void { print("begin nya") var stone = Int(2) { didSet { // (1) print("set stone") // (2) // print("set stone, \(self)") } } print("end nya") return { print(stone) } } } func main() { var cap: (() -> Void)? = nil do { print("---1---") let cat = Cat() print("---2---") cap = cat.nya() } // end of `cat` print("---3---") cap = nil print("---4---") } main()
Version:
swift-4.1.1-RELEASE
Output:
---1--- init cat ---2--- begin nya end nya deinit cat ---3--- ---4---
Error:
/usercode/main.swift:30:9: warning: variable 'cap' was written to, but never read var cap: (() -> Void)? = nil ^
Avatar
omochimetaru 10/1/2018 3:47 PM
@Kishikawa Katsumi ↑のコードで、(2)のコメントアウトを解除すると、出力結果が変わって、 deinit cat---3--- の後になりました。
3:48 PM
ここから推測するに、 didSet に self が含まれていて、かつ、 そのcomputed propertyがescapeしているときは、 escapeしてるcomputed propertyが、そのdidSetで見ているselfをキャプチャしているっぽいですね。
Avatar
Kishikawa Katsumi 10/1/2018 3:49 PM
^ 現状の整理としては正しいと思います。
Avatar
omochimetaru 10/1/2018 3:49 PM
岸川さんのコードだと、 Cat -> Cat.wall -> Cat.wall.onChanged -> self (Cat) でサイクル
3:50 PM
昼に書いた
didSetのコードブロックはselfをキャプチャしないので
↑これは条件付きで間違いだったみたいです。
Avatar
Kishikawa Katsumi 10/1/2018 3:52 PM
いや、私もそう思ってたんですけど、昨日調べてるときにはdidSetのメソッド呼び出しがなかったら起こらないことが先に見つかったので、didSetはキャプチャするんだっけと、私もよくわからなくなっていました。
3:53 PM
現実的にはdidSetはselfをweakキャプチャする手段がたぶんないから、中身をselfを参照しない形に直す必要がある、というのが昨日の段階ですね。
Avatar
omochimetaru 10/1/2018 3:54 PM
// (1) print("set stone") // (2) // print("set stone, \(self)") この状態だったらサイクルしなかったので、 weak var wself = wself var stone = Int(2) { didSet { < wself を使う > } } (edited)
3:55 PM
↑こうすればいける気もします。クロージャの キャプチャリストの形式ではダメそうですね
Avatar
Kishikawa Katsumi 10/1/2018 3:55 PM
なるほど。そっちの方がシンプルですね。
Avatar
omochimetaru 10/1/2018 3:56 PM
@swiftbot class Cat { init() { print("init cat") } deinit { print("deinit cat") } func nya() -> () -> Void { print("begin nya") weak var wself = self var stone = Int(2) { didSet { guard let self = wself else { return } print(self) } } print("end nya") return { print(stone) } } } func main() { var cap: (() -> Void)? = nil do { print("---1---") let cat = Cat() print("---2---") cap = cat.nya() } // end of `cat` print("---3---") cap = nil print("---4---") } main()
🛠 1
Avatar
swiftbot BOT 10/1/2018 3:56 PM
Author icon
omochimetaru
class Cat { init() { print("init cat") } deinit { print("deinit cat") } func nya() -> () -> Void { print("begin nya") weak var wself = self var stone = Int(2) { didSet { guard let self = wself else { return } print(self) } } print("end nya") return { print(stone) } } } func main() { var cap: (() -> Void)? = nil do { print("---1---") let cat = Cat() print("---2---") cap = cat.nya() } // end of `cat` print("---3---") cap = nil print("---4---") } main()
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:26:9: warning: variable 'cap' was written to, but never read var cap: (() -> Void)? = nil ^ /usercode/main.swift:12:23: error: pattern matching in a condition requires the 'case' keyword guard let self = wself else { ^ case /usercode/main.swift:12:27: error: expression pattern of type 'Cat' cannot match values of type 'Cat?' guard let self = wself else { ^~~~ ?
Avatar
omochimetaru 10/1/2018 3:57 PM
@swift-4.2.4 class Cat { init() { print("init cat") } deinit { print("deinit cat") } func nya() -> () -> Void { print("begin nya") weak var wself = self var stone = Int(2) { didSet { guard let self = wself else { return } print(self) } } print("end nya") return { print(stone) } } } func main() { var cap: (() -> Void)? = nil do { print("---1---") let cat = Cat() print("---2---") cap = cat.nya() } // end of `cat` print("---3---") cap = nil print("---4---") } main()
Avatar
---1--- init cat ---2--- begin nya end nya deinit cat ---3--- ---4---stderr:<stdin>:26:9: warning: variable 'cap' was written to, but never read var cap: (() -> Void)? = nil ^
Avatar
omochimetaru 10/1/2018 3:57 PM
一応これでサイクルしないようです
Avatar
Kishikawa Katsumi 10/1/2018 3:58 PM
私も確認しました 👍
Avatar
omochimetaru 10/1/2018 3:58 PM
didSetの中でも wself => self の再代入、うまくうごくんですねえ。
3:58 PM
(もしかしてバグを引き当てるんじゃないかと思ったけど)
Avatar
そこにdidSet書けたのか〜と思ったんですけど、なるほどfunc定義するのと同じですね。確か関数内関数を定義してself参照したその関数をどこかに渡すとリーク作れたと思います。
Avatar
Kishikawa Katsumi 10/2/2018 7:22 AM
もうちょっと細かい挙動を調べてintendedかどうか聞いてみようかと思います。
Avatar
確か前にここでCodableで20個フィールド越えると問題があるって誰か言ってませんでしたっけ? 問題を踏んだのかまだ調べつつなんですが、空オブジェクトになってしまう
Avatar
omochimetaru 10/3/2018 7:09 AM
20個超えてさらにあえてズラすとかじゃないっけ
Avatar
それでMac壊したの私ですかね
😫 2
7:10 AM
Generic+20個+ズラす
7:10 AM
=> メモリ破壊
Avatar
あえてズラす
ズラさなければ関係ないのか...じゃあ違う事象っぽいのでもう少し調べて見ますんorz
Avatar
↓みたいなパターンマッチしたい・・・。 switch keyPath { case \Foo.bar[let i].baz.qux[let key]: ... default: .... }
🙂 1
Avatar
omochimetaru 10/9/2018 2:50 AM
The review of SE-0231 — Optional Iteration begins now and runs through October 12, 2018. 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...
2:50 AM
The review of SE-0230 — Flatten nested optionals resulting from try? begins now and runs through October 8th, 2018. 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 fe...
2:50 AM
2つのSEがレビュー中
2:50 AM
// Swift 4: 'Int??' // Swift 5: 'Int?' let result = try? database?.countOfRows(matching: predicate) // Swift 4: 'String??' // Swift 5: 'String?' let myString = try? String(data: someData, encoding: .utf8) // Swift 4: '[String: Any]??' // Swift 5: '[String: Any]?' let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
2:50 AM
let array: [Int]? = nil for? element in array { ... } // Equivalent to if let unwrappedArray = array { for element in unwrappedArray { ... } }
2:51 AM
try? の挙動変更と、 for? 文の追加
Avatar
for element in array? の方が馴染みそう。 if case let foo? = foo とかを考えると。
3:04 AM
try??. の挙動と合わせて提案されてる挙動で良いと思うけど、そもそも try? を使うことがほとんどないなぁ。
Avatar
omochimetaru 10/9/2018 3:05 AM
例外が飛んだ時にデフォルト値を使う時に、 try? + ?? をよく使う
3:05 AM
例えばJSONをストレージとして使ってるときに、初回インストール時はファイルが無かったりするので読み込めないんだけど
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
3:06 AM
Imitating optional chaining A syntactically less disruptive approach, the idea of which is denoting an optional iteration by following the sequence expression with ?: let array: [Int]? = [1, 2, 3] for element in sequence? { ... }
Avatar
omochimetaru 10/9/2018 3:12 AM
このくだりが読めない・・・ Although Swift clearly has better alternatives to check for nil, this special case of optional pattern usage is very important in relation to the alternative currently discussed. The same tendency can be seen in for element in sequence?, but since binding the unwrapped sequence would effectively almost never be required, we omit the case let _? = part preceding sequence? as a rule of thumb.
3:13 AM
てか、この代替案が棄却された理由を述べてるわけじゃない?
Avatar
わからん・・・
3:16 AM
Although Swift clearly has better alternatives to check for nil
Swift は nil をチェックするための明らかにより良い選択肢を持っているけれども
3:17 AM
これは Optional Binding とかのことを言ってる?
Avatar
omochimetaru 10/9/2018 3:17 AM
その上でサンプルコードがたくさんあるので、if caseとかfor caseのことっぽい。
Avatar
this special case of optional pattern usage is very important in relation to the alternative currently discussed.
この Optional パターンの特別なケース( if case let foo? = foo のことと思われる)は、今議論している選択肢 ( for element in sequence? のことと思われる)との関係の面でとても重要だ。
3:18 AM
ここまでは意味わかるんよね。
3:19 AM
あー、でもこのあと
The same tendency can be seen in for element in sequence?,
だから、 the alternative currently discussed は for element in sequence? じゃない?
Avatar
omochimetaru 10/9/2018 3:19 AM
unwrapした左辺値が必要ないから省略したのが for element in seq? という書き方なんだぞ
3:20 AM
って話?だとすると、代替案がダメな理由がやっぱ書いてないですよね。
Avatar
The same tendency can be seen in for element in sequence?,
同様の傾向は for element in sequence? でも見られる
Avatar
omochimetaru 10/9/2018 3:21 AM
そのtendencyがよくわかんないんだけど、if case let と同じようなスタイルでイケてるって言いたいんですかね。
Avatar
"very important` な傾向じゃないかなぁ?
Avatar
omochimetaru 10/9/2018 3:22 AM
あ、なるほど。
Avatar
自信はない
3:24 AM
but since binding the unwrapped sequence would effectively almost never be required
しかし、 unwrapped sequence のバインディングは事実上ほぼ必要とされないので
3:25 AM
この unwrapped sequence のバインディングっていうのは for case let element? in sequence? みたいなことを言ってる??
Avatar
omochimetaru 10/9/2018 3:25 AM
それはforループの内側で、sequence? から取り出した sequence を使える必要はないって言ってるんだと思う
3:25 AM
sequence? -> sequence -> element っていう2段階取り出しにおいて。
Avatar
ああ
3:27 AM
最初の
Although Swift clearly has better alternatives to check for nil
if case let _? = optionalInt { ... } のことか。
3:27 AM
そこから読み違えてた。
3:28 AM
このパラグラフは if case let _? = optionalInt { ... } を上の一覧に入れなかった理由を説明してるだけなのか。
Avatar
omochimetaru 10/9/2018 3:30 AM
if case let _? = optionalInt { ... }
we omit the case let _? = part preceding sequence? as a rule of thumb.
Avatar
特に反対意見は述べられてない気がするなぁ。
Avatar
omochimetaru 10/9/2018 3:30 AM
omitしたのは 左辺の部分って意味じゃない?
3:30 AM
特に反対意見は述べられてない気がするなぁ。
まあ結局そこですよね
Avatar
うん、単に if case let _? = optionalInt { ... } を↓に挙げなかったよって言ってるだけかと。 let array: [Int?] = [1, 2, nil] // Match using an optional pattern. for case let element? in array { ... } // Match using an enum case pattern. for case let .some(element) in array { ... } let optionalInt: Int? = 0 // Match using an optional pattern. if case let unwrapped? = optionalInt { ... } // Match using an enum case pattern. if case let .some(unwrapped) = optionalInt { ... } // Match using optional binding. if let unwrapped = optionalInt { ... } // Match against .some using an optional pattern switch optionalInt { case let unwrapped?: print() case nil: print() } // Match against .some using enum case pattern switch optionalInt { case let .some(unwrapped): print() case nil: print() }
3:31 AM
なんで for element in sequenc? が less disruptive なのにそれを採用しなかったんだろう??
3:33 AM
A terminating ? sigil here can be thought of as bringing the for loop into the optional chain with the sequence and mirrors the force-unwrapping case (sequence!). On the other hand, this alternative sytactically has a lot in common with optional patterns that are used as sugar for pattern-matching .some(value). The following examples are equivalent per statement type:
最初、これ↑の On the other hand 以降で反対意見述べてんのかと思ったけど、これって単に前半で Optional chaning や Forcen unwrapping との関係を、後半でパターンマッチングとの関係を述べてるだけやんね?
(edited)
3:34 AM
tkrajacic What is your evaluation of the proposal? +1 but with a strong preference for the for element in elements? {…} syntax
3:34 AM
まったく同じ気持ちだ。
Avatar
omochimetaru 10/9/2018 3:34 AM
スレッドのほうですか
3:34 AM
コメント100超えてる・・・
Avatar
I am a +1 on this proposal (except for the ? location). It is fairly common to get a sequence from a dictionary or optional chaining, and a lightweight syntax for handling it that fits with the many other uses of ? would be appropriate. You could make the same argument abou...
3:37 AM
Ben Cohen も for element in sequenc? を推してる?
3:38 AM
ざっと見たところ ? は後ろにすべき派が多いように見える。
Avatar
omochimetaru 10/9/2018 3:38 AM
なるほどw
3:38 AM
AltConsは普通に選択肢になってることもあるのか。
3:39 AM
必ず論破してからproposalになるんだと思いこんでた。
Avatar
? を後ろにした方が、↓のような構文の可能性も残すと思うんよね。 let a: Int? = foo(x?) // foo の戻り値の型は Int
3:40 AM
↓よりわかりやすいと思う。 let a: Int? = x.map { foo($0) }
Avatar
omochimetaru 10/9/2018 3:41 AM
それな〜
3:41 AM
メソッドだったら ?. でシュッと書けるのに、引数だと map になるの、
3:41 AM
微妙な気持ちになるんですよね。
Avatar
パターンパッチングや Optional Chain も含めて、 foo? はラップされてる値とラップしている Optional を分離する記法という意味で統一感がある。
Avatar
omochimetaru 10/9/2018 3:42 AM
かといって foo(x?) はどうなんだと思うところもあるけども・・・
3:42 AM
if let x = foo(a?, b, c?) { ... } みたいな
Avatar
foo(x?)foo が Optional を返す場合は flatten してほしいね。
3:43 AM
let number: Int? = Int(string?)
Avatar
omochimetaru 10/9/2018 3:43 AM
お、そのflattenはまさに、try? の話と同根かな
Avatar
?. がそういう挙動だから、 try? も含めてそうなるのが自然だと思うんよね。
Avatar
omochimetaru 10/9/2018 3:45 AM
そうか確かに。
3:45 AM
?. でメソッドの型がoptionalの時、式の型はflattenされて1重か。
Avatar
↓は OK なのに struct Bar {} struct Foo { func bar() -> Bar? { return Bar() } } extension Int { func foo() -> Foo? { return Foo() } } let x = 42 let bar: Bar? = x.foo()?.bar() // ✅ OK
3:49 AM
↓はエラーなのは変だと思う。 struct Bar {} struct Foo { func bar() -> Bar? { return Bar() } } extension Int { func foo() throws -> Foo { return Foo() } } let x = 42 let bar: Bar? = try? x.foo().bar() // ⛔ NG
3:50 AM
↓こうしろということかもしれないけど。 struct Bar {} struct Foo { func bar() -> Bar? { return Bar() } } extension Int { func foo() throws -> Foo { return Foo() } } let x = 42 let bar: Bar? = (try? x.foo())?.bar() // ✅ OK (edited)
Avatar
omochimetaru 10/9/2018 3:52 AM
確かにthrowsは . で素通しできても良さそうですね。
3:52 AM
どうせtryは式木全体にかかるんだから
3:53 AM
メソッドチェーンのどこがthrowsなのかの明示は必須でなくても良い。
3:53 AM
たまにそれ踏んで3番目のパターンを書く事あるので
3:54 AM
proposal機運あるレベル (edited)
Avatar
for element in sequence? で通るなら、今後の Optional 便利構文の可能性を開くという意味でいい気がする。
4:02 AM
for? はきつい。
Avatar
@swiftbot struct RGBA<Channel> { var red: Channel var green: Channel var blue: Channel var alpha: Channel } let rgbaArray = [RGBA(red: 255, green: 127, blue: 0, alpha: 255)] rgbaArray.withUnsafeBufferPointer { rgbaPointer in print(rgbaPointer[0]) rgbaPointer.withMemoryRebound(to: UInt8.self) { uint8Pointer in print(uint8Pointer[0]) } }
🛠 1
Avatar
swiftbot BOT 10/9/2018 9:21 AM
Author icon
koher
struct RGBA<Channel> { var red: Channel var green: Channel var blue: Channel var alpha: Channel } let rgbaArray = [RGBA(red: 255, green: 127, blue: 0, alpha: 255)] rgbaArray.withUnsafeBufferPointer { rgbaPointer in print(rgbaPointer[0]) rgbaPointer.withMemoryRebound(to: UInt8.self) { uint8Pointer in print(uint8Pointer[0]) } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
Fatal error: Current stack trace: 0 libswiftCore.so 0x00007fc6d3c55750 _swift_stdlib_reportFatalError + 171 1 libswiftCore.so 0x00007fc6d39c3ad6 <unavailable> + 1366742 2 libswiftCore.so 0x00007fc6d3bfe383 <unavailable> + 3703683 3 libswiftCore.so 0x00007fc6d39c3ad6 <unavailable> + 1366742 4 libswiftCore.so 0x00007fc6d3b2fd80 <unavailable> + 2858368 5 libswiftCore.so 0x00007fc6d3af7ded <unavailable> + 2629101 6 libswiftCore.so 0x00007fc6d3af7c20 UnsafeBufferPointer.withMemoryRebound<A, B>(to:_:) + 42 10 libswiftCore.so 0x00007fc6d39bde30 Array.withUnsafeBufferPointer<A>(_:) + 172 12 swift 0x0000000000fed1ce <unavailable> + 12505550 13 swift 0x0000000000ff1692 <unavailable> + 12523154 ...
9:21 AM
Avatar
omochimetaru 10/9/2018 9:21 AM
とりあえず
9:21 AM
Intになってそう
Avatar
↑これ死ぬのなんでかわかります? withMemoryRebound の使い方間違えてる?
9:22 AM
あれ?
Avatar
omochimetaru 10/9/2018 9:22 AM
RGBA<Int>(red: 255, green: 127, blue: 0, alpha: 255)
Avatar
手元でやると一つ目の print 実行されるのに
9:24 AM
@omochimetaru それはミスだったけど、 UInt8 にしてもクラッシュするし、 Int でも動くはずでは? @swift-4.2.4 struct RGBA<Channel> { var red: Channel var green: Channel var blue: Channel var alpha: Channel } let rgbaArray = [RGBA<UInt8>(red: 255, green: 127, blue: 0, alpha: 255)] rgbaArray.withUnsafeBufferPointer { rgbaPointer in print(rgbaPointer[0]) rgbaPointer.withMemoryRebound(to: UInt8.self) { uint8Pointer in print(uint8Pointer[0]) } }
Avatar
exit status: 4 with stderr:Fatal error: Current stack trace: 0 libswiftCore.so 0x00007f9ac2b0f120 _swift_stdlib_reportFatalError + 168 1 libswiftCore.so 0x00007f9ac2866d0a <unavailable> + 1502474 2 libswiftCore.so 0x00007f9ac2aa419e <unavailable> + 3850654 3 libswiftCore.so 0x00007f9ac2866d0a <unavailable> + 1502474 4 libswiftCore.so 0x00007f9ac29ff0d9 <unavailable> + 3174617 5 libswiftCore.so 0x00007f9ac29d7d56 <unavailable> + 3013974 6 libswiftCore.so 0x00007f9ac29d7c90 UnsafeBufferPointer.withMemoryRebound<A, B>(to:_:) + 42 10 libswiftCore.so 0x00007f9ac2861280 Array.withUnsafeBufferPointer<A>(_:) + 97 12 swift 0x0000000001043efe <unavailable> + 12861182 13 swift 0x0000000001048022 <unavailable> + 12877858 14 swift 0x00000000004f8b42 <unavailable> + 1018690 15 swift 0x00000000004df0bb <unavailable> + 913595 16 swift 0x00000000004da3f0 <unavailable> + 893936 17 swift 0x000000000048a348 <unavailable> + 566088 18 libc.so.6 0x00007f9ac54b3740 __libc_start_main + 240 19 swift 0x0000000000488009 <unavailable> + 557065 #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 0x00007f9ac6d89390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f9ac29ff0e1 $Ss18_fatalErrorMessage__4file4line5flagss5NeverOs12StaticStringV_A2HSus6UInt32VtFTf4nnddn_n (/usr/lib/swift/linux/libswiftCore.so+0x3070e1) #5 0x00007f9ac29d7d56 $SSr17withMemoryRebound2to_qd_0_qd__m_qd_
Avatar
archetype を UInt8 に rebound しようとして拒否されている感じですかねぇ。
9:27 AM
-O だと specialize されるので通る。
Avatar
これは、本来は正しく rebound されるべきという理解で間違ってないですか?
9:27 AM
あーなるほど。 specialize でうまくいくのか。
Avatar
Unsafe なのでグレーだと思います。
Avatar
omochimetaru 10/9/2018 9:28 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
9:28 AM
ここで落ちてる気がするけどなぜかメッセージが空なんですよね
9:28 AM
CommandLineSandbox`merged Swift.UnsafeMutableBufferPointer.withMemoryRebound<A, B>(to: A1.Type, _: (Swift.UnsafeMutableBufferPointer<A1>) throws -> B1) throws -> B1:
9:28 AM
↑スタックトレース
Avatar
グレーなのか。でもこれできなかったら画像処理とか辛い・・・。
Avatar
omochimetaru 10/9/2018 9:30 AM
@swift-4.2.4 struct RGBA<Channel> { var red: Channel var green: Channel var blue: Channel var alpha: Channel } print(MemoryLayout<RGBA<UInt8>>.stride) print(MemoryLayout<UInt8>.stride) (edited)
Avatar
4 1 (edited)
Avatar
omochimetaru 10/9/2018 9:30 AM
アウトだ。
9:30 AM
BufferPointerを使わなければよいのでは?
9:30 AM
生のポインタの方でやってみたらいけそう。
Avatar
RGBA<Int> じゃなくて RGBA<UInt8>
9:31 AM
が本来やりたいこと。
Avatar
omochimetaru 10/9/2018 9:31 AM
BufferPointerは配列的なメモリを扱うやつだから、strideがあってて [0]は[0], [1]は[1]にマップするものなのかも
9:32 AM
リリースビルドで通るのはこのチェックが > _debugPrecondition(MemoryLayout<Element>.stride == MemoryLayout<T>.stride) (edited)
Avatar
なるほど。
Avatar
omochimetaru 10/9/2018 9:32 AM
debugPreconditionだからリリースのときは無いんじゃないか?
Avatar
The type to temporarily bind the memory referenced by this buffer. The type T must have the same size and be layout compatible with the pointer’s Element type.
9:32 AM
ほんとだ。
Avatar
omochimetaru 10/9/2018 9:34 AM
@swift-4.2.4 struct RGBA<Channel> { var red: Channel var green: Channel var blue: Channel var alpha: Channel } let rgbaArray = [RGBA<UInt8>(red: 255, green: 127, blue: 0, alpha: 255)] rgbaArray.withUnsafeBufferPointer { (rgbaBufferPointer: UnsafeBufferPointer<RGBA<UInt8>>) in rgbaBufferPointer.baseAddress!.withMemoryRebound(to: UInt8.self, capacity: rgbaBufferPointer.count * 4) { (uint8Pointer: UnsafePointer<UInt8>)in print(uint8Pointer[0]) print(uint8Pointer[1]) print(uint8Pointer[2]) print(uint8Pointer[3]) } }
Avatar
255 127 0 255
Avatar
omochimetaru 10/9/2018 9:34 AM
これで期待通り
9:35 AM
(要素0のときクラッシュしそうなので ! のところは直して
Avatar
@omochimetaru なるほど。ありがとう。 Array から UnsafePointer を取る一番スマートな方法って、↑か withUnsafeBytesbaseAddress をとることかな?
Avatar
omochimetaru 10/9/2018 9:39 AM
他に無い気がします
9:40 AM
withUnsafeBytesが返すのも結局 UnsafeRawBufferPointer なのか。 (edited)
Avatar
うん。
9:41 AM
mutable だったら引数に渡すときに & でとれるのに、どういう API の整理なんだろう?
9:41 AM
あれ?引数にはそのまま渡せるんだっけ?
Avatar
omochimetaru 10/9/2018 9:41 AM
内側の withMemoryRebound のcapacityの計算が簡単だから 型付きのBufferのほうを使うのが良さそうです
Avatar
↓これはできるんだった。 @swift-4.2.4 func foo(_ p: UnsafePointer<Int>) { print(p.pointee) } let a = [2, 3, 5] foo(a)
Avatar
2
Avatar
omochimetaru 10/9/2018 9:43 AM
var rgbaArray = [RGBA<UInt8>(red: 255, green: 127, blue: 0, alpha: 255)] func constF(_ p: UnsafePointer<RGBA<UInt8>>) {} func mutableF(_ p: UnsafeMutablePointer<RGBA<UInt8>> ) {} constF(rgbaArray) mutableF(&rgbaArray)
9:43 AM
こうですね
9:43 AM
UnsafePointerはshared referenceだからそのまま渡せる。 UnsafeMutablePointerは inout reference だから、inout引数のときと同じく & をつける
9:44 AM
func constF(_ p: UnsafePointer<RGBA<UInt8>>) {} // 心の目 func constF(_ p: shared RGBA<UInt8>) {} func mutableF(_ p: UnsafeMutablePointer<RGBA<UInt8>> ) {} // 心の目 func constF(_ p: inout RGBA<UInt8>) {} (edited)
9:44 AM
shared referenceはまだ無いけど。
Avatar
心の目w
9:46 AM
withUnsafePointer がほしい・・・。
Avatar
omochimetaru 10/9/2018 9:46 AM
extension書くとか!
9:47 AM
@swift-4.2.4 struct RGBA<Channel> { var red: Channel var green: Channel var blue: Channel var alpha: Channel } var rgbaArray = [RGBA<UInt8>(red: 255, green: 127, blue: 0, alpha: 255)] func constF(_ p: UnsafeBufferPointer<RGBA<UInt8>>) {} func mutableF(_ p: UnsafeMutableBufferPointer<RGBA<UInt8>> ) {} constF(rgbaArray) mutableF(&rgbaArray)
Avatar
exit status: 1 with stderr:<stdin>:11:8: error: cannot convert value of type '[RGBA<UInt8>]' to expected argument type 'UnsafeBufferPointer<RGBA<UInt8>>' constF(rgbaArray) ^~~~~~~~~ <stdin>:12:10: error: '&' used with non-inout argument of type 'UnsafeMutableBufferPointer<RGBA<UInt8>>' mutableF(&rgbaArray) ^~~~~~~~~~
Avatar
omochimetaru 10/9/2018 9:47 AM
こっちはできないのおかしいやろw
9:47 AM
ArrayのAPIはBufferPointerでのアクセスしか許してないのに、 コンパイラの自動変換は単体ポインタだけで、BufferPointerには行かない・・・
9:48 AM
あ〜 C Interop が目的の機能だからかな〜
9:48 AM
でもそれならそれで C から import された関数に対してだけ、変換されるべきって木もするなあ
Avatar
let rgbaArray = [RGBA<UInt8>(red: 255, green: 127, blue: 0, alpha: 255)] rgbaArray.withUnsafeBytes { (buf) in for x in buf.bindMemory(to: UInt8.self) { print(x) } } UInt8 列として取り出すだけならこれが一番簡単なような。
Avatar
C/C++ で書かれた画像処理ライブラリにポインタとして渡すのが目的なので、ポインタで取り出す必要があります😂 (edited)
Avatar
そのときは length も同時にわたすのですか?
Avatar
そうですね。
9:53 AM
今のケースでは、 C++ のクラスのコンストラクタに width, height の情報と一緒に渡します。
9:54 AM
( C API 経由で) (edited)
Avatar
omochimetaru 10/9/2018 9:55 AM
RGBA<UInt8> のメモリレイアウトが変わったらオシマイだから心配だ・・・ (edited)
9:56 AM
特にそういう機運は無いけれども。
Avatar
アライメント的な話で?
9:58 AM
とりあえず動くようになりました。ありがとうございました。 > @omochimetaru @rintaro
Avatar
omochimetaru 10/9/2018 9:58 AM
アライメントとストライド、フィールドの敷き詰め方などなど。ジェネリクスも絡んでるし。
Avatar
RGBA<UInt8> が単純な 4 バイトでないメモリレイアウトになったら辛いなぁ。
10:01 AM
今そこを前提に他の言語では実現しづらいいい感じの API が作れるので・・・。
Avatar
norio_nomura 10/9/2018 2:09 PM
@swift-4.2.4 -frontend -repl struct RGBA<Channel> { var red: Channel var green: Channel var blue: Channel var alpha: Channel } MemoryLayout<RGBA<UInt8>>.stride // 4 MemoryLayout<RGBA<UInt8>>.offset(of: \RGBA<UInt8>.red) // 0 MemoryLayout<RGBA<UInt8>>.offset(of: \RGBA<UInt8>.green) // 1 MemoryLayout<RGBA<UInt8>>.offset(of: \RGBA<UInt8>.blue) // 2 MemoryLayout<RGBA<UInt8>>.offset(of: \RGBA<UInt8>.alpha) // 3 (edited)
Avatar
// r0 : Int = 4 // r1 : Int? = Optional(0) // r2 : Int? = Optional(1) // r3 : Int? = Optional(2) // r4 : Int? = Optional(3) (edited)
Avatar
@swift-4.2.4 let a: [Int]??? = [1] let c: Int = a???.count ?? 0 print(c)
Avatar
exit status: 2 with stderr:error: unable to invoke subcommand: /usr/bin/swift-swift (No such file or directory) ```
Avatar
@swift-4.2.4 let a: [Int]??? = [1] let c: Int = a???.count ?? 0 print(c)
Avatar
1
Avatar
?. のハテナの数増やせるの知らなかった(そして数が正しくないと動かない)
Avatar
おお、知らなかった・・・ < ??.
Avatar
John_McCall 4h We've seen repeated requests for things like x?.count + 1, yes. I don't think there's a way to "clean up the concepts" here that could possibly lead to something like let x = y? meaning anything that wouldn't introduce its own much more serious complexity and compatibility problems. (edited)
Avatar
x?.count + 1 はなしだけど、↓はやりたいんだよなぁ。 let foo: Foo = Foo(x?) ?? Foo("foo") (edited)
8:28 AM
x? を使わないと↓になってしまう。 let foo: Foo = x.map { Foo($0) } ?? Foo("foo")
Avatar
引数部分だけとかが良いのかな
8:28 AM
昨日出てきた配列をUnsafePointerとして渡せるみたいなやつも
8:28 AM
func(array)array.withUnsafePointer { func($0) } になってるわけだから
Avatar
基本的に Optional はそのままで取り回すべきじゃなくてすぐにハンドリングすべきで (edited)
8:29 AM
そう考えると ?. が一番使いたいのって ?? との組み合わせだと思うんよね。
Avatar
func(x?) が x.map { func($0) } になるって範囲なら同種の仕組みだ。
Avatar
そう考えると、 x?.count + 1(x?.count + 1) ?? 1 にするんなら (x?.count ?? 0) + 1 にできるからできなくていい。
8:31 AM
ただ、演算子も関数であることを考えると x?.count + 1+(x?.count, 1) だからできるはずなんよね。
Avatar
これが出来る不思議ってのもありますよね。 var x: Int? = 1 x? = 1
Avatar
x.map { $0.count + 1 } なのか (x.map { $0.count } ?? 0) + 1 なのかとか
8:32 AM
@rintaro なんだこりゃ!w
Avatar
@rintaro えー、それできるんですか? Swift 1 の頃の名残ではなく?
Avatar
たしかに実行できるw
8:32 AM
Avatar
たしか Swift 1 の頃は末尾 ? が使えたはず。
Avatar
x が non nil のときだけ代入される。
Avatar
@swift-4.2.4 var x: Int??? x = 1 print(x) x? = 2 print(x) x?? = 3 print(x) x??? = 4 print(x)
Avatar
Optional(Optional(Optional(1))) Optional(Optional(Optional(2))) Optional(Optional(Optional(3))) Optional(Optional(Optional(4)))stderr:<stdin>:3:7: warning: expression implicitly coerced from 'Int???' to 'Any' print(x) ^ <stdin>:3:7: note: force-unwrap the value to avoid this warning print(x) ^ !!! <stdin>:3:7: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(x) ^ as Any <stdin>:5:7: warning: expression implicitly coerced from 'Int???' to 'Any' print(x) ^ <stdin>:5:7: note: force-unwrap the value to avoid this warning print(x) ^ !!! <stdin>:5:7: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(x) ^ as Any <stdin>:7:7: warning: expression implicitly coerced from 'Int???' to 'Any' print(x) ^ <stdin>:7:7: note: force-unwrap the value to avoid this warning print(x) ^ !!! <stdin>:7:7: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(x) ^ as Any <stdin>:9:7: warning: expression implicitly coerced from 'Int???' to 'Any' print(x) ^ <stdin>:9:7: note: force-unwrap the value to avoid this warning print(x) ^ !!! <stdin>:9:7: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(x) ^ as Any
Avatar
ウケる
8:33 AM
ハテナが多すぎるとエラーだ。
Avatar
昨日、 for element in sequenc? を許せば将来許容できる構文に x? = 1 みたいなのもあり得るって書こうとして、いつ使うんだ?と思って止めたけどまさかすでにできたとはw
8:35 AM
ちゃんと↓で更新されないw @swift-4.2.4 var x: Int? = nil x? = 42 print(x)
Avatar
nilstderr:<stdin>:3:7: warning: expression implicitly coerced from 'Int?' to 'Any' print(x) ^ <stdin>:3:7: note: provide a default value to avoid this warning print(x) ^ ?? <#default value#> <stdin>:3:7: note: force-unwrap the value to avoid this warning print(x) ^ ! <stdin>:3:7: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(x) ^ as Any
Avatar
var x: Int??? x = 1 print(x) x? = 2 print(x) x?? = 3 print(x) x??? = 4 print(x)
8:35 AM
最初に1を入れたから動いたのか。
Avatar
@omochimetaru
ハテナが多すぎるとエラーだ。
それは警告では?
8:36 AM
print したときの。
Avatar
@swift-4.2.4 var x: Int??? x???? = 4 print(x)
Avatar
exit status: 1 with stderr:<stdin>:2:5: error: cannot use optional chaining on non-optional value of type 'Int' x???? = 4 ~~~~^ <stdin>:3:7: warning: expression implicitly coerced from 'Int???' to 'Any' print(x) ^ <stdin>:3:7: note: force-unwrap the value to avoid this warning print(x) ^ !!! <stdin>:3:7: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(x) ^ as Any
Avatar
errorです
Avatar
ああ、数がそろってないと、って意味?
Avatar
以下なら大丈夫。
8:36 AM
何段目のsomeで判定するかが変わってるのか・・・?
Avatar
変わってそう
8:37 AM
確か Swift 1 の頃に、右辺値でもこれあったんよね。
Avatar
@swift-4.2.4 func check1(_ x: Int??) { var x = x x? = 2 print(x as Any) } func check2(_ x: Int??) { var x = x x?? = 2 print(x as Any) } var x1: Int?? = .none var x2: Int?? = .some(.none) var x3: Int?? = .some(.some(1)) check1(x1) check2(x1) print("--") check1(x2) check2(x2) print("--") check1(x3) check2(x3) (edited)
Avatar
nil nil -- Optional(Optional(2)) Optional(nil) -- Optional(Optional(2)) Optional(Optional(2)) (edited)
Avatar
変わった。
Avatar
struct S { var prop: Int } var s: S? s?.prop = 1 とかだと、結構つかってる人いるんじゃないかな?
Avatar
あ〜
8:42 AM
それの .prop が無い状態ってことか〜〜
Avatar
vicktorManuel 10/10/2018 4:54 PM
@swift-4.0.3 let a: [Int]??? = [1] let c: Int = a???.count ?? 0 print(c)
Avatar
Usage: @swift40 [SWIFT_OPTIONS] `​`​`​ [Swift Code] `​`​`​
Avatar
vicktorManuel 10/10/2018 4:54 PM
@swift-4.2.4 let a: [Int]??? = [1] let c: Int = a???.count ?? 0 print(c)
Avatar
Usage: @swift42 [SWIFT_OPTIONS] `​`​`​ [Swift Code] `​`​`​
Avatar
トリプルバッククォートで囲むとできますよ
Avatar
vicktorManuel 10/10/2018 4:55 PM
すみません笑ありがと!
4:57 PM
@swift-4.2.4 ''' var x: Int? = nil x? = 42 print(x) '''
Avatar
Usage: @swift42 [SWIFT_OPTIONS] `​`​`​ [Swift Code] `​`​`​
Avatar
vicktorManuel 10/10/2018 4:58 PM
😩
4:58 PM
var x: Int? = nil x? = 42 print(x)`
4:58 PM
大丈夫笑
4:59 PM
@swift-4.2.4 var x: Int? = nil x? = 42 print(x)
Avatar
nilstderr:<stdin>:4:7: warning: expression implicitly coerced from 'Int?' to 'Any' print(x) ^ <stdin>:4:7: note: provide a default value to avoid this warning print(x) ^ ?? <#default value#> <stdin>:4:7: note: force-unwrap the value to avoid this warning print(x) ^ ! <stdin>:4:7: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(x) ^ as Any
Avatar
vicktorManuel 10/10/2018 5:00 PM
@swift-4.2.4 ´´´ let a: [Int]??? = [1] let c: Int = a???.count ?? 0 print(c) ´´´
Avatar
Usage: @swift42 [SWIFT_OPTIONS] `​`​`​ [Swift Code] `​`​`​
Avatar
vicktorManuel 10/10/2018 5:00 PM
@swift-4.2.4 let a: [Int]??? = [1] let c: Int = a???.count ?? 0 print(c)`
Avatar
1
Avatar
@swift-4.2.4 public struct Foo { @usableFromInline private var a: Int = 42 @inlinable public mutating func f() -> Int { a += 1 return a } }
Avatar
exit status: 1 with stderr:<stdin>:3:5: error: '@usableFromInline' attribute can only be applied to internal declarations, but 'a' is private @usableFromInline private var a: Int = 42 ^~~~~~~~~~~~~~~~~~ <stdin>:5:9: error: var 'a' is private and cannot be referenced from an '@inlinable' function a += 1 ^ <stdin>:3:35: note: var 'a' is not '@usableFromInline' or public @usableFromInline private var a: Int = 42 ^ <stdin>:6:16: error: var 'a' is private and cannot be referenced from an '@inlinable' function return a ^ <stdin>:3:35: note: var 'a' is not '@usableFromInline' or public @usableFromInline private var a: Int = 42 ^
Avatar
@swift-4.2.4 public struct Foo { @usableFromInline internal private(set) var a: Int = 42 @inlinable public mutating func f() -> Int { a += 1 return a } }
Avatar
no output
Avatar
↑、 @usableFromInlineprivate だとダメなのに、 private(set)a += 1 があるのに通るのは大丈夫なんでしょうか?見えてはいけないものが公開されてない?
Avatar
バグだと思います。
10:15 PM
@swift-main public struct Foo { @usableFromInline internal private(set) var bar: Int { get { return 42 } set { print(newValue) } } @inlinable public mutating func f() -> Int { bar += 1 return bar } }
Avatar
swiftNightly BOT 10/10/2018 10:15 PM
exit status: 134 with stderr:SIL verification failed: function_ref inside fragile function cannot reference a private or hidden symbol: (SingleFunction && RefF->isExternalDeclaration()) || RefF->hasValidLinkageForFragileRef() Verifying instruction: -> // function_ref Foo.bar.setter %16 = function_ref @$s4main3FooV3barSivs : $@convention(method) (Int, @inout Foo) -> () // user: %17 %17 = apply %16(%15, %7) : $@convention(method) (Int, @inout Foo) -> () In function: // Foo.f() sil [serialized] @$s4main3FooV1fSiyF : $@convention(method) (@inout Foo) -> Int { // %0 // users: %20, %7, %1 bb0(%0 : @trivial $*Foo): debug_value_addr %0 : $*Foo, var, name "self", argno 1 // id: %1 %2 = metatype $@thin Int.Type // user: %14 %3 = metatype $@thin Int.Type // user: %6 %4 = integer_literal $Builtin.Int2048, 1 // user: %6 // function_ref Int.init(_builtinIntegerLiteral:) %5 = function_ref @$sSi22_builtinIntegerLiteralSiBi2048__tcfC : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int // user: %6 %6 = apply %5(%4, %3) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int // user: %14 %7 = begin_access [modify] [unknown] %0 : $*Foo // users: %18, %17, %9 %8 = alloc_stack $Int // users: %19, %15, %14, %12 %9 = load [trivial] %7 : $*Foo // user: %11 // function_ref Foo.bar.getter %10 = function_ref @$s4main3FooV3barSivg : $@convention(method) (Foo) -> Int // user: %11 %11 = apply %10(%9) : $@convention(method) (Foo) -> Int // user: %12 store %11 to [trivial] %8 : $*Int // id: %12 // function_ref static Int.+= infix(_:_:) %13 = function_ref @$sSi2peoiyySiz_SitFZ : $@convention(method) (@inout Int, Int, @thin Int.Type) -> () // user: %14 %14 = apply %13(%8, %6, %2) : $@convention(method) (@inout Int, Int, @thin Int.Type) -> () %15 = load [trivial] %8 : $*Int
Avatar
なるほど。 nightly での↑はコンパイルエラーになっているわけじゃなくてコンパイラがクラッシュしてる??
Avatar
SIL verification failedはそうですね
1:44 AM
SILが生成された後(optimizeされた後?)にSIL verificationステージがあって
1:45 AM
コンパイラの前段にバグがあってもここで検出して死ぬようになってる
Avatar
コンパイラの前段にバグがあってもここで検出して死ぬようになってる
Logic failure だ・・・。
Avatar
nightly だからというか、verification ステージが効いているかどうかだと思います。Xcode 付属のものは何もしないので。
Avatar
えっ、そうなんですか。
Avatar
@swift-4.2.4 public struct Foo { @usableFromInline internal private(set) var bar: Int { get { return 42 } set { print(newValue) } } @inlinable public mutating func f() -> Int { bar += 1 return bar } }
Avatar
exit status: 134 with stderr:SIL verification failed: function_ref inside fragile function cannot reference a private or hidden symbol: (SingleFunction && RefF->isExternalDeclaration()) || RefF->hasValidLinkageForFragileRef() Verifying instruction: -> // function_ref Foo.bar.setter %16 = function_ref @$S4main3FooV3barSivs : $@convention(method) (Int, @inout Foo) -> () // user: %17 %17 = apply %16(%15, %7) : $@convention(method) (Int, @inout Foo) -> () In function: // Foo.f() sil [serialized] @$S4main3FooV1fSiyF : $@convention(method) (@inout Foo) -> Int { // %0 // users: %20, %7, %1 bb0(%0 : $*Foo): debug_value_addr %0 : $*Foo, var, name "self", argno 1 // id: %1 %2 = metatype $@thin Int.Type // user: %14 %3 = metatype $@thin Int.Type // user: %6 %4 = integer_literal $Builtin.Int2048, 1 // user: %6 // function_ref Int.init(_builtinIntegerLiteral:) %5 = function_ref @$SSi22_builtinIntegerLiteralSiBi2048__tcfC : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int // user: %6 %6 = apply %5(%4, %3) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int // user: %14 %7 = begin_access [modify] [unknown] %0 : $*Foo // users: %18, %17, %9 %8 = alloc_stack $Int // users: %19, %15, %14, %12 %9 = load [trivial] %7 : $*Foo // user: %11 // function_ref Foo.bar.getter %10 = function_ref @$S4main3FooV3barSivg : $@convention(method) (Foo) -> Int // user: %11 %11 = apply %10(%9) : $@convention(method) (Foo) -> Int // user: %12 store %11 to [trivial] %8 : $*Int // id: %12 // function_ref static Int.+= infix(_:_:) %13 = function_ref @$SSi2peoiyySiz_SitFZ : $@convention(method) (@inout Int, Int, @thin Int.Type) -> () // user: %14 %14 = apply %13(%8, %6, %2) : $@convention(method) (@inout Int, Int, @thin Int.Type) -> () %15 = load [trivial] %8 : $*Int // user:
Avatar
出荷版には直ってるはずだからverificationはスキップするのか。
Avatar
バグで nightly でも解消されてないということは、類似の報告がなければバグレポ出しておいた方が良さそうですね。
Avatar
そうですね。ありがとうございます!
Avatar
ちょっと今立て込んでるので夜にでも類似レポがないか調べて出しておきます🙂
Avatar
WWDCで言ってた #if hasTargetEnvironment(simulator) ってまだ使えないんですかね
10:55 AM
怒られる。
Avatar
hasいらなくないでしょうか
10:56 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
10:56 AM
targetEnvironment()
10:57 AM
4.1実装なのでXcode 9.3から使えるはずです
Avatar
あら、本当だ。スライドが違うのか。 https://developer.apple.com/videos/play/wwdc2018/401/?time=1825
Hear about the latest advancements in Swift, the safe, fast, and expressive language. Find out about improvements to build times, code...
Avatar
わーおそんなとこ間違ってることあるんですね……
😲 2
Avatar
いけました。ありがとうございます!
Avatar
@usableFromInline の件、作りました。 https://bugs.swift.org/browse/SR-8969
👍 2
Avatar
vicktorManuel 10/12/2018 4:08 PM
Swift 4.2 is finally out! This article will take you through the advancements and changes the language has to offer in its latest version.
Avatar
Hey all, At Apple we are making it a priority to support high-quality tooling for all Swift developers, including those working on non-Apple platforms. We want to collaborate with the open-source community and focus our efforts on building common infrastructure that can be s...
🎉 7
Avatar
ウオォと思って貼りにきたらノムラさんがもう貼ってた!w
2:18 AM
SwiftのLSP対応のプロジェクトが開始するそうです。これができればVSCodeなどで快適にSwift開発できるようになります。Windowsサポートとかも見据えてるのかな?
Avatar
コンテキストはよくわからないですけど、最近 Facebook 勢が SourceKit for windows パッチ投げまくってたので、SourceKit が動けば LSP サーバ自体は Swift なのでいけるようになるんじゃないかと思ってます。
Avatar
よく見たら「開始する」じゃなくて「1ヶ月前から始まった?」
2:27 AM
ほう、Facebook勢というのは、いつもの2,3人とは別の人達ですか?
2:27 AM
compnerdさんとか。
Avatar
いつものですねw
Avatar
ああ。彼らはFacebook勢だったのか。
Avatar
Harutaka Matsumoto 10/16/2018 1:15 PM
こんばんは はじめまして、松本です #general で少し話しましたが、突然ですが一つ提案があります シェルスクリプトのSwift版、swiftShellを作りたいです
1:20 PM
要するに、せっかくターミナルのREPLでインタプリタの使い方ができ、ファイルシステムがこれだけ標準で充実してるのだから、シェルスクリプトでやっていることを全てSwiftで実用できるようにしよう!というものです
Avatar
Kishikawa Katsumi 10/16/2018 1:22 PM
@Harutaka Matsumoto 今でもシェルスクリプトの代替としてSwiftを使うことはできますが、作ろうとしているのはどういうものですか?
Avatar
Harutaka Matsumoto 10/16/2018 1:29 PM
はい しかし、FoundationのFile Systemをそのまま使うと、コードが不必要に長くなってしまうと思います それをlist(of:)だとか、makeDirectory(at:)だとか、シェルの表現を踏襲しかつswiftyな名前で実装することで、シェル経験者の移行がスムーズ、かつ初心者でも簡単に使えるものにしたいのです
Avatar
Kishikawa Katsumi 10/16/2018 1:34 PM
ああ、なるほど。それはよいアイデアだと思います 😄
Avatar
Harutaka Matsumoto 10/16/2018 1:34 PM
また、C言語でいうpopen関数がにあたるものがSwift APIにありません これを実装することで、gnuplotだとかqdpだとかheasoftなどの学術で使われるCUIアプリケーションの中までコマンドを届かせることができ、シェルの完全なる代替となります
Avatar
Kishikawa Katsumi 10/16/2018 1:35 PM
https://github.com/kareman/SwiftShell 既存のものだと同名で同じようなコンセプトのプロジェクトがありますね。このプロジェクトもう少しプリミティブな機能セットでおっしゃってるほどリッチなものではないようですが。
A Swift framework for shell scripting. Contribute to kareman/SwiftShell development by creating an account on GitHub.
Avatar
Harutaka Matsumoto 10/16/2018 1:42 PM
おおー同名であったのですね知りませんでした💦 多分入出力周りをやった感じですかね?
1:44 PM
あとbashのrunに皮をかぶせたあたり?
Avatar
Kishikawa Katsumi 10/16/2018 1:44 PM
そうですね。IOと外部コマンドの実行を簡単に扱えるAPIを提供しているようです、今のところ。
Avatar
Harutaka Matsumoto 10/16/2018 1:45 PM
とりあえずそうですね、もっとリッチにやりたいです
1:45 PM
そしてコンパイラ的なSwiftとシームレスに利用できるように
Avatar
良いですね、僕も同じような事を考えたことがあります
2:20 PM
SwiftPMでコマンドラインツールは作れますが、現状の課題としては、ライブラリを使うためにPackage.Swiftが必要なために、 ワンファイルで済ませられないのが使いにくい点だと思ってて
2:22 PM
コメント文とかで依存ライブラリを定義しておけば、裏でPackage.swiftを生成してくれて、SwiftPM経由で実行してくれる、発火用のコマンドを提供する みたいな仕様だと良いのかなあと思ってます
Avatar
Marathon makes it easy to write, run and manage your Swift scripts 🏃 - JohnSundell/Marathon
2:22 PM
これが近そうですね
Avatar
マラソンとかミントとかも目的は近いんですけど、なんかそのツール自体が根っこにある感じで、個人的にはしっくりきていないです
Avatar
コメント文とかで依存ライブラリを定義しておけば、裏でPackage.swiftを生成してくれて、SwiftPM経由で実行してくれる、発火用のコマンドを提供する
これを実現するにはマラソンなどのビルドツールが根っこに無いと難しくないですか?
(edited)
Avatar
Generate your swifty boilerplate. Contribute to omochi/gysb development by creating an account on GitHub.
2:26 PM
↑を作った時にやったのでやればできます
2:27 PM
こっちはコメントじゃなくてgysb.jsonで依存ライブラリを定義できる。
2:27 PM
SwiftPMのビルド中間物のキャッシュが効くようにテクってるところはある。
Avatar
あ、 > ツール自体が根っこにある感じ これは外部のよく分からんビルドシステムに乗るのが気持ち悪いっていう話か
Avatar
それプラス、スクリプトというか、コマンドラインツールのダウンローダー?を含めたパッケージマネージャみたいになってませんか?
Avatar
まあ、ダウンローダーは過多な気がしますね
Avatar
「インストールされているもの一覧」がある、のか、違う感じというか。 ファイル単体で完結して再配布性もあるのがスクリプトの魅力かなと思ってます
2:37 PM
どちらかというとマラソンとかが解決してるのは、Carthageみたいなしっかりしたツールを作るときに、インストーラーの実装をサボれるのが価値に感じます
Avatar
↑のシェルスクリプトを作る話だと、標準ライブラリに無いAPIを提供するライブラリとPackage.swiftを生成するビルドシステムを分けたほうが良さそうですね。
Avatar
同意です あともう一つ観点があって、Xcodeのフルサポートが欲しいんですよね〜
Avatar
xcodeprojの生成の話ですか?
Avatar
ですね
Avatar
マラソンはそこらへんをうまくやってくれます
Avatar
なるほど。
Avatar
#generalより …Swiftで書かれたshellがあっても面白そうですよね… 「Swiftで書かれたshell」と「Swiftで書けるshell」では随分違うね。
Avatar
そこ自分が口頭で話してたときに意図を汲み取れてなかった可能性が @Harutaka Matsumoto さんの話の流れからSwiftで書けるshellの方が正しそうです
Avatar
Harutaka Matsumoto 10/17/2018 9:53 PM
おはようございます 皆さん反応ありがとうございます😊
9:58 PM
えーとですね、とりあえず雛形のリポジトリを作りましたhttps://github.com/HarutakaMatsumoto/swiftShell/blob/master/README.md
This is the shell script language of Swift. It's swifty, and you can use it with existing codes seamlessly. - HarutakaMatsumoto/swiftShell
10:01 PM
ここのREADMEの完成イメージにもある通り、SwiftのREPLで主に使えるような、シェルコマンドの代替となる関数をサポートするライブラリーを作ろうということです
10:04 PM
今までの反応を見ると少し誤解があるようなのですが、これで伝わりましたかね?💦
Avatar
REPLモードをシェルとして使いたいって事だったんですね
Avatar
Harutaka Matsumoto 10/18/2018 8:10 AM
そうですそうです
Avatar
Harutaka Matsumoto 10/18/2018 8:26 AM
地道にやっていきますが、オプションやマイナーなコマンドは正直手に余るので、皆さんのお力添えを頂けると嬉しいです
Avatar
vicktorManuel 10/18/2018 5:23 PM
@Harutaka Matsumoto wow! 面白いね
5:25 PM
私はこれに取り組んでいます
Avatar
↓壊れた。本当は async の中の_foo の呼び出しがコンパイルエラーでないといけないと思う。 @swift-4.2.4 import Dispatch struct S { var a: Int = 42 mutating func foo() { func _foo() { if a == 0 { return } a -= 1 print(a) DispatchQueue.main.async { _foo() } } foo() } } var s = S() s.foo()
Avatar
exit status: 134 with stderr:Argument must be @noescape function type: %62 = copy_block %61 : $@convention(block) () -> () // users: %72, %70 A partial_apply with @inout_aliasable may only be used as a @noescape function type argument. UNREACHABLE executed at /home/buildnode/jenkins/workspace/oss-swift-4.2-package-linux-ubuntu-16_04/swift/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp:883! #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 0x00007f24e55b8390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f24e3cf7428 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35428) #5 0x00007f24e3cf902a abort (/lib/x86_64-linux-gnu/libc.so.6+0x3702a) #6 0x00000000040a3fed llvm::llvm_unreachable_internal(char const*, char const*, unsigned int) (/usr/bin/swift+0x40a3fed) #7 0x0000000000dcac45 checkStaticExclusivity(swift::SILFunction&, swift::PostOrderFunctionInfo*, swift::AccessSummaryAnalysis*) (/usr/bin/swift+0xdcac45) #8 0x0000000000d53bb3 swift::SILPassManager::runPassOnFunction(unsigned int, swift::SILFunction*) (/usr/bin/swift+0xd53bb3) #9 0x0000000000d546b1 swift::SILPassManager::runFunctionPasses(unsigned int, unsigned int) (/usr/bin/swift+0xd546b1) #10 0x0000000000d555e4 swift::SILPassManager::execute() (/usr/bin/swift+0xd555e4) #11 0x00000000005c1648 swift::SILPassManager::executePassPipelinePlan(swift::SILPassPipelinePlan const&) (/usr/bin/swift+0x5c1648) #12 0x0000000000d5c615 swift::runSILDiagnosticPasses(swift::SILModule&) (/usr/bin/swift+0xd5c615) #13 0x00000000004de5ef performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) (/usr/bin/swift+0x4de5ef) #14 0x00000000004da3f0 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*,
Avatar
あれ?
10:01 AM
Linux だから?
10:01 AM
実行時エラーには変わりないけど、まだマシなメッセージが出てる。
Avatar
いえ、macOSでもmasterで同エラー再現しました。
Avatar
手元で実行したら
10:02 AM
無限再帰呼び出しになった
10:02 AM
foo()の末尾でfoo()呼んでるのが辺じゃないですか?
Avatar
あれ? _foo じゃないとダメだ
Avatar
やりたかったのはfoo()の末尾で_foo()を呼ぶコード?
Avatar
あー、しかも async を main で呼んだらダメだな。 (edited)
Avatar
rintaroさんが試したのはmasterでコンパイラクラッシュの事か。
10:04 AM
Xcode10ではコンパイルはできた。
Avatar
元のはアプリ中のコードだったので。
10:05 AM
これ、でもコンパイル通るのはいいのかな?まあ、 inout とかでも複雑なケースで実行時エラーだしいいのか??
10:06 AM
@swift-4.2.4 import Dispatch func run(_ body: @escaping () -> Void) { body() } struct S { var a: Int = 42 mutating func foo() { func _foo() { if a == 0 { return } a -= 1 print(a) run(_foo) } _foo() } } var s = S() s.foo()
Avatar
exit status: 1 with stderr:<stdin>:14:13: error: nested function with an implicitly captured inout parameter can only be used as a non-escaping argument run(_foo) ^
Avatar
@swift-4.2.4 func run(_ body: @escaping () -> Void) { body() } struct S { var a: Int = 3 mutating func foo() { func _foo() { if a == 0 { return } a -= 1 print(a) run { _foo() } } _foo() } } var s = S() s.foo() (edited)
Avatar
exit status: 134 with stderr:Argument must be @noescape function type: %53 = partial_apply [callee_guaranteed] %52(%0) : $@convention(thin) (@inout_aliasable S) -> () // users: %56, %55 A partial_apply with @inout_aliasable may only be used as a @noescape function type argument. UNREACHABLE executed at /home/buildnode/jenkins/workspace/oss-swift-4.2-package-linux-ubuntu-16_04/swift/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp:883! #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 0x00007f2ef3166390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f2ef18a5428 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35428) #5 0x00007f2ef18a702a abort (/lib/x86_64-linux-gnu/libc.so.6+0x3702a) #6 0x00000000040a3fed llvm::llvm_unreachable_internal(char const*, char const*, unsigned int) (/usr/bin/swift+0x40a3fed) #7 0x0000000000dcac45 checkStaticExclusivity(swift::SILFunction&, swift::PostOrderFunctionInfo*, swift::AccessSummaryAnalysis*) (/usr/bin/swift+0xdcac45) #8 0x0000000000d53bb3 swift::SILPassManager::runPassOnFunction(unsigned int, swift::SILFunction*) (/usr/bin/swift+0xd53bb3) #9 0x0000000000d546b1 swift::SILPassManager::runFunctionPasses(unsigned int, unsigned int) (/usr/bin/swift+0xd546b1) #10 0x0000000000d555e4 swift::SILPassManager::execute() (/usr/bin/swift+0xd555e4) #11 0x00000000005c1648 swift::SILPassManager::executePassPipelinePlan(swift::SILPassPipelinePlan const&) (/usr/bin/swift+0x5c1648) #12 0x0000000000d5c615 swift::runSILDiagnosticPasses(swift::SILModule&) (/usr/bin/swift+0xd5c615) #13 0x00000000004de5ef performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) (/usr/bin/swift+0x4de5ef) #14 0x00000000004da3f0 swift::performFrontend(llvm (edited)
Avatar
おや、手元の Mac では普通に 2, 1, 0 が表示されて、 Linux だとクラッシュ。いずれにしても、 run(_foo) はコンパイルエラーなのに run { _foo() } がコンパイルエラーでないのはまずい気が。
Avatar
structのselfキャプチャってどうなるのか調べてみたら
Avatar
どうなってるのかというか、本来コンパイラがエラーにしておくべきなんじゃないかな?
Avatar
普通にやると > Closure cannot implicitly capture a mutating self parameter (edited)
10:12 AM
それで、 [self] でキャプチャすると > > Cannot assign to property: 'self' is an immutable capture
10:12 AM
クロージャ { } で書いてるとそうなんだけど、 func 形式でクロージャを作ったときに
10:13 AM
この辺のチェックがもれて変な事になっているきがする
Avatar
先にローカル funcreturn したりして試したんだけど、
10:13 AM
使うだけなら non escaping になって
Avatar
あ、でも違うエラーになるんだな > Nested function with an implicitly captured inout parameter can only be used as a non-escaping argument
Avatar
return しようとすると escaping になったから
10:14 AM
チェックは働いてるけど↑のパターンが漏れてる気がする。
Avatar
本来は _foo がエスケープ使用されると、キャプチャモードに昇格するみたいなイメージっぽいですね。 (edited)
Avatar
クロージャ式は再帰できないけど、ローカル関数だと再帰できるのが漏れてる原因かも
Avatar
_foo の昇格が _fooの中で生じた場合がみそかな
Avatar
バグっぽい?ならバグレポしとこうかな。
Avatar
import Dispatch func indirect(_ f: @escaping () -> Void) { f() } struct S { var a: Int = 42 mutating func foo() { func cl() { a = 50 indirect { cl() } } cl() print(a) } } var s = S() s.foo()
10:16 AM
↑いろいろなところをちょっと変えるだけで正しくコンパイルエラーになるw
👌🏼 1
Avatar
master だとクラッシュしちゃってるし、完全にバグですね。
Avatar
この辺の実装大変そうだなあ
10:17 AM
Visitorパターンだらけで読みづらいし・・・
Avatar
じゃあバグレポしときます。
❤ 1
10:18 AM
@omochimetaru indirect { cl() } 見て、え、そんな未知の構文あったの?って思ったら関数だったw indirectenum のでハイライトされるから。
Avatar
あw
10:18 AM
紛らわしい名前だった。
Avatar
vicktorManuel 10/19/2018 6:29 PM
This code creates two classes, Address and Person, and it creates two instances to represent Ray and Brian. class Address { var fullAddress: String var city: String init(fullAddress: String, city: String) { self.fullAddress = fullAddress self.city = city } } class Person { var name: String var address: Address init(name: String, address: Address) { self.name = name self.address = address } } var headquarters = Address(fullAddress: "123 Tutorial Street", city: "Appletown") var ray = Person(name: "Ray", address: headquarters) var brian = Person(name: "Brian", address: headquarters)` Suppose Brian moves to the new building across the street, so you update his record like this: brian.address.fullAddress = "148 Tutorial Street" What's going on here? What's wrong with this?
Avatar
Kishikawa Katsumi 10/20/2018 1:26 AM
Brian and Ray share the headquarters instance. brian.address.fullAddress = "148 Tutorial Street" This also updates Ray's address 😵
👌🏼 1
Avatar
@swift-main protocol P{} extension P{ func a(){ P.a(self)() } } (edited)
Avatar
swiftNightly BOT 10/21/2018 7:21 AM
exit status: 134 with stderr:not existential UNREACHABLE executed at /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-16_04/swift/lib/SILGen/SILGenConvert.cpp:1008! 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-ssl-93eb7dfa/Sources/CNIOOpenSSL/include -I /Libraries/.build/checkouts/crypto-36ec1aea/Sources/CCryptoOpenSSL/include -I /Libraries/.build/checkouts/crypto-36ec1aea/Sources/CBcrypt/include -I /Libraries/.build/checkouts/crypto-36ec1aea/Sources/CBase32/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 -I /Libraries/.build/checkouts/SwiftBacktrace-fcbf89ea/Sources/CSwiftBacktrace/include -I /Libraries/.build/checkouts/SwiftBacktrace-fcbf89ea/Sources/Clibunwind/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/CNIOOpenSSL.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CCryptoOpenSSL.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/crypto-36ec1aea/Sources/CBcrypt/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/crypto-36ec1aea/Sources/CBase32/include/module.modulemap -Xcc -fmodule-map-fil (edited)
Avatar
正しく壊れた
Avatar
P.aじゃなくてSelf.aじゃないと参照できなさそうな気がした
Avatar
@swift-main protocol P{} extension P{ func a(){ Self.a(self)() } }
Avatar
swiftNightly BOT 10/21/2018 7:28 AM
stderr:<stdin>:4:10: warning: all paths through this function will call itself func a(){ ^
Avatar
おー、ちゃんと警告まで出してくれるのか
7:29 AM
@swift-main protocol P{} extension P{ func a(){} func b() { P.a(self)() } }
Avatar
swiftNightly BOT 10/21/2018 7:29 AM
exit status: 134 with stderr:not existential UNREACHABLE executed at /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-16_04/swift/lib/SILGen/SILGenConvert.cpp:1008! 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-ssl-93eb7dfa/Sources/CNIOOpenSSL/include -I /Libraries/.build/checkouts/crypto-36ec1aea/Sources/CCryptoOpenSSL/include -I /Libraries/.build/checkouts/crypto-36ec1aea/Sources/CBcrypt/include -I /Libraries/.build/checkouts/crypto-36ec1aea/Sources/CBase32/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 -I /Libraries/.build/checkouts/SwiftBacktrace-fcbf89ea/Sources/CSwiftBacktrace/include -I /Libraries/.build/checkouts/SwiftBacktrace-fcbf89ea/Sources/Clibunwind/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/CNIOOpenSSL.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CCryptoOpenSSL.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/crypto-36ec1aea/Sources/CBcrypt/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/crypto-36ec1aea/Sources/CBase32/include/module.modulemap -Xcc -fmodule-map-fil
Avatar
aの中でaを呼び出してるからクラッシュするのかと思ってたんですけど、P.aがまずかったのか
Avatar
https://bugs.swift.org/browse/SR-75 古ーいバグなんです。
👀 1
Avatar
2桁の時代のバグ…
Avatar
FWIW, the Swift for TensorFlow team is actively looking to hire an engineer to work on Swift for Windows and help drive surrounding ecosystem efforts but are struggling with finding someone who is interested and able. If you know of anyone who could be a good fit, please get...
2:39 AM
SwiftForTFチームで、Windows対応ニキも募集してるけど人が見つからねえって
2:39 AM
ラトナーが書いてる!
2:42 AM
少なくともグーグル資本でSwiftのWindows対応モチベがあるってことでアツい
Avatar
これ Google の力で Windows 対応されたら Apple 以外に広がってる感があっていいね。
Avatar
MSのコンパイラエンジニアがラトナーみたいに転職してくれたらいいな
2:45 AM
機械学習分野ってWindowsユーザー居なそうなイメージだけど
2:46 AM
エコシステムを広げるためって書いてるし広げたいんですね
Avatar
Windows ユーザー自体は多いから、 Windows で機械学習しようとしたときに Swift ならサポートされてて簡単に始められるよって状況を作りたいのかな?
Avatar
Completely agree with this point. FWIW, I consider #1 to be the default option that we should go with unless there is something clearly better. We have had this behavior for years now and (as you say) it is highly precedented in other languages. I agree it is suboptimal, ...
6:36 AM
FloatがComparable壊れてるスレなんだけど
6:36 AM
Introduce an new/additive <=> operator, returning less/greater/equal/unordered
6:37 AM
この案良さそう
6:38 AM
こっちを使ったsortとかが優先オーバーロードされたら結構な問題は解決
Avatar
この前話してた宇宙船演算子だ。コンテクストは違うけど。 https://discordapp.com/channels/291054398077927425/291054454793306112/495628056321458196
6:54 AM
<=> の結果に .unordered があると <=> を活用するの面倒そうだけど、基本は < を使って sort とかだけが <=> を使えばいいのかな?
7:01 AM
したがって有限半順序集合は閉路を持たない有限な単純有向グラフと自然に同一視できる。
7:01 AM
これに対応してそう・・・?
Avatar
グラフって分断された孤島ができてもいいんだっけ?って思ったけど、↓の定義だと良さそう。 https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%A9%E3%83%95%E7%90%86%E8%AB%96#%E5%BD%A2%E5%BC%8F%E7%9A%84%E3%81%AA%E5%AE%9A%E7%BE%A9
12:55 PM
NaN が孤立するよね?
Avatar
特に駄目な気はしないです
12:57 PM
そこからいろんな議論ができるし
12:59 PM
連結グラフ(れんけつグラフ, connected graph)は、グラフ上の任意の2頂点間に道が存在するグラフのことである。
Avatar
「道が存在する」って、向きは考慮しなくてもいいのかな?ある頂点を起点として任意の頂点に到達できるという意味ではなく? (edited)
1:02 PM
形式的な定義が載ってなくてよくわからない
1:03 PM
A → B ↓ CBC の間にも「道が存在する」と言っていいのかな?
1:04 PM
とりあえず FloatDouble の比較は有限半順序集合になりそう。
Avatar
無向グラフを前提にしてますね (edited)
1:07 PM
有向グラフはおもちさんが貼ってくれたリンクの有向グラフと連結度って項目が詳しいですね
🙏 1
Avatar
Hi please how make a request GET with swift 4 , method get not work on my projet my data is array of json object [{}, {}, {}] .
Avatar
I have my API that always returns [{}, {}, {}] an array of Json, how can I decode it with swift 4.2, if someone has already had this case I'm listening. my method taps on on GET request.
Avatar
You mean about Codable? struct Empty: Codable {} ... JSONDecoder().decode([Empty].self, from: data) I think this way can work well.
Avatar
@JohnLight The following code is runnable one. @swift-4.2.4 import Foundation struct Empty: Codable, CustomStringConvertible { var description: String { return "{}" } } let json = "[{}, {}, {}]" let decoded = try! JSONDecoder().decode([Empty].self, from: json.data(using: .utf8)!) print(decoded)
Avatar
[{}, {}, {}]
Avatar
@JohnLight You can get the JSON data in the following way, although I do not recommend it because it contains a synchronous networking operation. If you do it in a GUI app, it is better to use URLSession instead of Data(contentsOf:) to get JSON data from a server. import Foundation struct Empty: Codable {} let url = URL(string: "https://...") // Set an appropriate URL let jsonData = try! Data(contentsOf: url) let decoded = try! JSONDecoder().decode([Empty].self, from: jsonData) print(decoded) (edited)
2:10 AM
@koher
2:10 AM
look at this ^^
Avatar
Sorry, fixed my code.
2:12 AM
decode([Empty].self, ...
Avatar
Okay ^^
2:18 AM
I have the same error
2:18 AM
@koher
Avatar
@JohnLight You failed to decode the JSON.
2:20 AM
Maybe there is some mismatch between Utilisateur's implementation and the JSON file.
Avatar
yes i think so .
Avatar
It seems that Utilisateur has a property named solde and the JSON lacks it.
2:22 AM
[{}, {}, {}] does not have solde in {}
2:25 AM
Please show me your implementation of Utilisateur.
Avatar
@swiftbot import Foundation let json = """ [ { "id": 1, "solde": { "id": 1 } }, { "id": 2, "solde": { "id": 2 } }, { "id": 3, "solde": { "id": 3 } } ] """ struct Utilisateur: Codable { let id: Int let solde: [Solde] } struct Solde: Codable { let id: Int } let jsonData = json.data(using: .utf8)! let decoded = try! JSONDecoder().decode([Utilisateur].self, from: jsonData) print(decoded)
🛠 1
Avatar
Author icon
koher
import Foundation let json = """ [ { "id": 1, "solde": { "id": 1 } }, { "id": 2, "solde": { "id": 2 } }, { "id": 3, "solde": { "id": 3 } } ] """ struct Utilisateur: Codable { let id: Int let solde: [Solde] } struct Solde: Codable { let id: Int } let jsonData = json.data(using: .utf8)! let decoded = try! JSONDecoder().decode([Utilisateur].self, from: jsonData) print(decoded)
Version:
swift-4.1.1-RELEASE
Output:
Error:
Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "solde", intValue: nil)], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil)): file /home/buildnode/jenkins/workspace/oss-swift-4.1-package-linux-ubuntu-16_04/swift/stdlib/public/core/ErrorType.swift, line 184 Current stack trace: 0 libswiftCore.so 0x00007f2b8b1475c0 _swift_stdlib_reportFatalErrorInFile + 221 1 libswiftCore.so 0x00007f2b8aeb63dc <unavailable> + 1369052 2 libswiftCore.so 0x00007f2b8b0f0222 <unavailable> + 3703330 3 libswiftCore.so 0x00007f2b8b0f1689 <unavailable> + 3708553 4 libswiftCore.so 0x00007f2b8aeb5ad6 <unavailable> + 1366742 ...
2:56 AM
Avatar
あー、わかった
2:58 AM
@JohnLight The type of Utilisateur.solde must be Solde instead of [Solde].
Avatar
ok just that
3:01 AM
@koher
3:02 AM
i try but , i have the same error
3:02 AM
struct Utilisateur: Codable { let id: Int let solde: Solde let soldecrypto: Soldecrypto
Avatar
@JohnLight The JSON lacks some properties of Utilisateur. If they are optional, you need them as Optionals. import Foundation struct Utilisateur: Codable { let id: Int let solde: Solde let soldecrypto: Soldecrypto let nom: String let prenom: String let adresse: String? let ipadresse: String let codepostale: String? let ville: String? let reference: String let cgv: Int let genre: String let telephone: String let password: String let password_reset: String let password_updated: String let email: String let username: String let active: Int let iban: String? let bic: String? let load_identite: String? let load_justificatif_domicile: String? let validated: Int let roles: String let datenaissance: String let created: String } struct Solde: Codable { let id: Int let solde: Double let solde_old: Double let updated: String } struct Soldecrypto: Codable { let id: Int let bch_solde: Double let btc_solde: Double let eos_solde: Double let etc_solde: Double let eth_solde: Double let ltc_solde: Double let xrp_solde: Double let zec_solde: Double let updated: String } let url = URL(string: "https://preprod.cryptizy.com/test_bs78wazerty1235436ujYH/users")! let jsonData = try! Data(contentsOf: url) let decoded = try! JSONDecoder().decode([Utilisateur].self, from: jsonData) print(decoded) (edited)
3:07 AM
For example, I changed the type of adresse from String to String?.
3:07 AM
I have no idea about if the JSON is corrupted or those properties are really optional.
Avatar
ok i try with optional ,
Avatar
Good it works
👍 1
3:21 AM
@koher
3:22 AM
i try with URLSession instead of Data(contentsOf
👍 2
3:26 AM
🙏👏 🚀 Thanks @koher
🙂 1
👏 1
Avatar
@swift-4.2.4 // @escaping だけど同期的にクロージャが実行されるだけの関数 func run(_ body: @escaping () -> Void) { body() } // 値型を非同期的に更新するための機能を提供 struct Updater<Object: AnyObject, Target> { let object: Object let keyPath: ReferenceWritableKeyPath<Object, Target> func update(_ body: (inout Target) throws -> Void) rethrows { try body(&object[keyPath: keyPath]) } } // 値型、これの状態を @escaping をまたいで更新したい struct FooState { var a: Int = 0 mutating func incrementA<Object: AnyObject>(with updater: Updater<Object, FooState>) { run { // @escaping なのでこの中では `self` を更新できない updater.update { state in // Updater を使って更新 state.a += 1 } } } } // FooState を保持する参照型 class Foo { var state: FooState = FooState() { didSet { print("didSet: \(state.a)") } } func bar() { state.incrementA(with: Updater<Foo, FooState>(object: self, keyPath: \Foo.state)) } } let foo = Foo() foo.bar() print(foo.state.a) (edited)
Avatar
didSet: 1 didSet: 0 0 (edited)
Avatar
@omochimetaru @takasek 前に話してた Updater が↑のようなパターンだと機能しないことがわかりました。
9:09 AM
statedidSet をなくせばちゃんとインクリメントされますが、 didSet を付けると incrementA を抜けたタイミングで値が書き戻されるようになって incrementA のスコープでの状態( a = 0 )で上書きされてしまいます。 (edited)
Avatar
なるほど。
9:24 AM
didSetがついてない場合にうまく動くのは、call by copy-restore が
9:24 AM
参照渡しに最適化される副作用ですね
9:24 AM
かつ、そういうパターンはLoEで実行時クラッシュになるはずなんだけど動いてしまうなあ?
9:25 AM
Simultaneous accesses to 0x100c02a20, but modification requires exclusive access.
9:25 AM
あいや、うごかないっすね。良かったよかった。
9:26 AM
state の didSet をなくせばちゃんとインクリメントされますが
どうやって確認しましたか? こちらでは手元のXcodeと #swiftbot-sandbox で動かない(クラッシュ)ことを確認できました。
(edited)
Avatar
@escaping またいで値型を更新したいってどういう状況ですか?
9:31 AM
withoutActuallyEscaping(_:do:) では対応できないです?
Avatar
@omochimetaru おや、 REPL に貼り付けたときだけ動くっぽい。
👀 1
9:45 AM
@rintaro 値型のメソッド内で非同期処理を行って、その結果を受けて自身を更新したいようなケースです。できないんですが、自身を保持している参照型インスタンスを引数に渡すことで、その参照型インスタンスを通して自身を更新できるという。
9:46 AM
withoutActuallyEscaping は初めて見たので今見てます。
Avatar
@swift-4.2.4 import Foundation struct Foo { var a = 0 mutating func bar() { func increment() { a += 1 } withoutActuallyEscaping(increment) { increment in DispatchQueue.main.async(execute: increment) } } } var foo = Foo() foo.bar() print(foo.a)
Avatar
exit status: 134 with stderr:Argument must be @noescape function type: %7 = begin_borrow %6 : $@callee_guaranteed () -> () // users: %12, %10, %9 A partial_apply with @inout_aliasable may only be used as a @noescape function type argument. UNREACHABLE executed at /home/buildnode/jenkins/workspace/oss-swift-4.2-package-linux-ubuntu-16_04/swift/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp:883! #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 0x00007fa146bad390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007fa1452ec428 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35428) #5 0x00007fa1452ee02a abort (/lib/x86_64-linux-gnu/libc.so.6+0x3702a) #6 0x00000000040a3fed llvm::llvm_unreachable_internal(char const*, char const*, unsigned int) (/usr/bin/swift+0x40a3fed) #7 0x0000000000dcac45 checkStaticExclusivity(swift::SILFunction&, swift::PostOrderFunctionInfo*, swift::AccessSummaryAnalysis*) (/usr/bin/swift+0xdcac45) #8 0x0000000000d53bb3 swift::SILPassManager::runPassOnFunction(unsigned int, swift::SILFunction*) (/usr/bin/swift+0xd53bb3) #9 0x0000000000d546b1 swift::SILPassManager::runFunctionPasses(unsigned int, unsigned int) (/usr/bin/swift+0xd546b1) #10 0x0000000000d555e4 swift::SILPassManager::execute() (/usr/bin/swift+0xd555e4) #11 0x00000000005c1648 swift::SILPassManager::executePassPipelinePlan(swift::SILPassPipelinePlan const&) (/usr/bin/swift+0x5c1648) #12 0x0000000000d5c615 swift::runSILDiagnosticPasses(swift::SILModule&) (/usr/bin/swift+0xd5c615) #13 0x00000000004de5ef performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) (/usr/bin/swift+0x4de5ef) #14 0x00000000004da3f0 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, vo
Avatar
@rintaro withoutActuallyEscaping@escaping でない関数を型の上では @escaping だけど同期的に実行される箇所で @escaping 化するためのものという理解で合ってますか? (edited)
Avatar
あれ?逆じゃないですか? (edited)
Avatar
ああ、途中で日本語が変になってた。
Avatar
本来、 @escaping ではないクロージャーは、 @escaping を求めている引数には渡せないけど
10:00 AM
コレを使うと escaping性についてハードキャストできる
Avatar
とはいえ、理解はあっていると思います。withoutActuallyEscaping 外に実際にエスケープされるなら使うべきでは無いです。
Avatar
今回のケースは本質的に @escaping じゃないといけないのでだめそうですね。
10:04 AM
↓みたいにすればいいのかな・・・。 struct Updater<Object: AnyObject, Target> { let object: Object let keyPath: ReferenceWritableKeyPath<Object, Target> func update(_ body: @escaping (inout Target) throws -> Void) rethrows { DispatchQueue.main.async { try body(&object[keyPath: keyPath]) } } }
Avatar
Hello, Swift Community. The review for SE-0230: Flatten nested optionals resulting from try? ran from September 29th through October 4th, 2018. You can find the review thread here. There was a lot of discussion about this proposal. Many people find the current behavior in...
😃 3
1:09 AM
try? の仕様変更の提案が採択された
1:09 AM
下位互換壊すやつは珍しいですね
1:11 AM
こういうのが通るとワクワクする
Avatar
たまに(try ? poo())?.foo()って書いててなんでじゃ!ってなるよな
Avatar
そうそうw
Avatar
これは良い変更ですね。
Avatar
Kishikawa Katsumi 10/29/2018 8:34 AM
CocoaPodsのPodspecでswift_versionは指定しなくても実行した環境のSWIFT_VERSIONが採用されるからOKと思っていたけど、プロジェクトに統合しないオプションを指定したときに(プロジェクト設定を変えずにビルドだけさせる)SWIFT_VERSIONが決められなくて困るんですね。。。
Avatar
Taylorじゃない方のSwiftです( ´・‿・`) ---
swift 11
Avatar
omochimetaru 11/2/2018 6:39 AM
コンパイラのバグみつけた import UIKit protocol HogeProtocol where Self : UIViewController {} protocol FugaProtocol : HogeProtocol {} extension FugaProtocol { func fuga() { print(self.parent) } } func foo(_ fuga: FugaProtocol) { fuga.fuga() } class ViewController: UIViewController, FugaProtocol { @IBOutlet var textView: UITextView! override func viewDidLoad() { super.viewDidLoad() } @IBAction func onButton() { foo(self) } }
6:41 AM
@swift-4.2.4 class Animal { func bark() { } } protocol HogeP where Self : Animal {} protocol FugaP : HogeP {} extension FugaP { func fuga() { self.bark() } } func foo(_ fuga: FugaP) { fuga.fuga() } class Cat : Animal, FugaP { } let cat = Cat() foo(cat) (edited)
Avatar
exit status: 134 with stderr:TYPE MISMATCH IN ARGUMENT 0 OF APPLY AT expression at [<stdin>:13:5 - line:13:15] RangeText="fuga.fuga()" argument value: %2 = open_existential_addr immutable_access %0 : $*FugaP to $*@opened("6E5774C4-DE6A-11E8-B850-46984C01C748") FugaP parameter type: $@opened("6E5774C4-DE6A-11E8-B850-46984C01C748") FugaP #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 0x00007f057ca93390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f057b1d2428 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35428) #5 0x00007f057b1d402a abort (/lib/x86_64-linux-gnu/libc.so.6+0x3702a) #6 0x0000000000d18138 swift::Lowering::SILGenFunction::emitApply(std::unique_ptr<swift::Lowering::ResultPlan, std::default_delete<swift::Lowering::ResultPlan> >&&, swift::Lowering::ArgumentScope&&, swift::SILLocation, swift::Lowering::ManagedValue, llvm::ArrayRef<swift::Substitution>, llvm::ArrayRef<swift::Lowering::ManagedValue>, swift::Lowering::CalleeTypeInfo const&, swift::Lowering::ApplyOptions, swift::Lowering::SGFContext) (/usr/bin/swift+0xd18138) #7 0x0000000000d1ad49 (anonymous namespace)::CallEmission::apply(swift::Lowering::SGFContext) (/usr/bin/swift+0xd1ad49) #8 0x0000000000d19cc4 swift::Lowering::SILGenFunction::emitApplyExpr(swift::Expr*, swift::Lowering::SGFContext) (/usr/bin/swift+0xd19cc4) #9 0x0000000000cad75d swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) (/usr/bin/swift+0xcad75d) #10 0x0000000000cbcc26 void llvm::function_ref<void (swift::Expr*)>::callback_fn<swift::Lowering::RValue swift::Lowering::SILGenFunction::emitOpenExistentialExpr<swift::Lowering::RValue, (anonymous namespace)::RValueEmitter::visitOpenEx (edited)
Avatar
omochimetaru 11/2/2018 6:42 AM
@swift-4.2.4 class Animal { func bark() { } } protocol HogeP where Self : Animal {} protocol FugaP : HogeP {} extension FugaP { func fuga() { self.bark() } } func foo(_ fuga: FugaP) { fuga.fuga() } class Cat : Animal, FugaP { } let cat = Cat() foo(cat)
Avatar
exit status: 134 with stderr:TYPE MISMATCH IN ARGUMENT 0 OF APPLY AT expression at [<stdin>:13:5 - line:13:15] RangeText="fuga.fuga()" argument value: %2 = open_existential_addr immutable_access %0 : $*FugaP to $*@opened("7DC7DDB8-DE6A-11E8-9C56-46984C01C748") FugaP parameter type: $@opened("7DC7DDB8-DE6A-11E8-9C56-46984C01C748") FugaP #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 0x00007f90afabc390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f90ae1fb428 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35428) #5 0x00007f90ae1fd02a abort (/lib/x86_64-linux-gnu/libc.so.6+0x3702a) #6 0x0000000000d18138 swift::Lowering::SILGenFunction::emitApply(std::unique_ptr<swift::Lowering::ResultPlan, std::default_delete<swift::Lowering::ResultPlan> >&&, swift::Lowering::ArgumentScope&&, swift::SILLocation, swift::Lowering::ManagedValue, llvm::ArrayRef<swift::Substitution>, llvm::ArrayRef<swift::Lowering::ManagedValue>, swift::Lowering::CalleeTypeInfo const&, swift::Lowering::ApplyOptions, swift::Lowering::SGFContext) (/usr/bin/swift+0xd18138) #7 0x0000000000d1ad49 (anonymous namespace)::CallEmission::apply(swift::Lowering::SGFContext) (/usr/bin/swift+0xd1ad49) #8 0x0000000000d19cc4 swift::Lowering::SILGenFunction::emitApplyExpr(swift::Expr*, swift::Lowering::SGFContext) (/usr/bin/swift+0xd19cc4) #9 0x0000000000cad75d swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) (/usr/bin/swift+0xcad75d) #10 0x0000000000cbcc26 void llvm::function_ref<void (swift::Expr*)>::callback_fn<swift::Lowering::RValue swift::Lowering::SILGenFunction::emitOpenExistentialExpr<swift::Lowering::RValue, (anonymous namespace)::RValueEmitter::visitOpenEx
Avatar
omochimetaru 11/2/2018 6:42 AM
@swift-main class Animal { func bark() { } } protocol HogeP where Self : Animal {} protocol FugaP : HogeP {} extension FugaP { func fuga() { self.bark() } } func foo(_ fuga: FugaP) { fuga.fuga() } class Cat : Animal, FugaP { } let cat = Cat() foo(cat)
Avatar
swiftNightly BOT 11/2/2018 6:42 AM
exit status: 1 with stderr:<stdin>:6:22: error: constraint with subject type of 'Self' is not supported; consider adding requirement to protocol inheritance clause instead protocol HogeP where Self : Animal {} ^
Avatar
omochimetaru 11/2/2018 6:43 AM
むむ 手元のXcode10.1ではコンパイルできて実行時エラー
6:44 AM
そもそも Self 制約がついてるのに Existential 化 できる時点でおかしい感じになっている
Avatar
https://github.com/apple/swift/pull/19844 最近再サポートされたっぽい。
This sort of worked in 4.2, then I banned it but it broke source comaptibility. Now that protocol superclass constraints are fully supported, let's allow this again, with some minor refactoring...
Avatar
omochimetaru 11/3/2018 4:25 AM
So both of these are equivalent and should work correctly: protocol P : SomeClass {} protocol P where Self : SomeClass {}
4:25 AM
お。良かった。
Avatar
Hi how make Table View swipe with swift4 ? I have try but it didn't work
Avatar
Swift 5ではStringUTF-16ではなくUTF-8で保持する様になるらしい。 https://twitter.com/jckarter/status/1059586744083988482
Thanks to @Ilseman's tireless work, Swift 5's String will use UTF-8 as its native representation, with great performance improvements! https://t.co/CYeCToAKUf
Avatar
正確には、ASCII or UTF-16で保持していたものをUTF-8にまとめた、という事か。 https://forums.swift.org/t/string-s-abi-and-utf-8/17676
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
もともとutf8じゃ無かったんですね
12:46 AM
最近CSVパーサを書いたのだけどこれの恩恵を受けられそう
Avatar
メモリ確保に関して知りたいのですが、staticな値を宣言するときに static var hoge: Int { return 0 } の場合と static let hoge: Int = 0 では、前者はメモリを呼び出し時にだけ確保されるような挙動になるのでしょうか?
5:43 AM
多めにstatic letを宣言したいケースに出くわしていて、var { get }で書くべきかletで書くべきか考えていてちょっと気になりました
Avatar
最適化でどちらも呼び出し側に展開されて同じになりそうな気もしますね。
Avatar
omochimetaru 11/6/2018 6:37 AM
前者は呼び出したときに値ができるだけで後者はストレージがずっと確保されると思います
Avatar
internal で利用箇所がすべてインライン化されてもストレージは消えない?
Avatar
omochimetaru 11/6/2018 6:39 AM
その型のオブジェクトに対するkeyPathによる動的なアクセスができるから
6:39 AM
他のアクセスが無いことを静的に保証できない気がする
Avatar
なるほど。
Avatar
omochimetaru 11/6/2018 6:42 AM
あれ、だめだ、MetaTypeにはkeyPath使えないっぽい
Avatar
let.swift struct Foo { static let bar: Int = 42 } print(Foo.bar) var.swift struct Foo { static var bar: Int { return 42 } } print(Foo.bar)
Avatar
omochimetaru 11/6/2018 6:43 AM
最適化の余地はありそうか
Avatar
LLVM IR の diff 貼ろうとしたらデカすぎて貼れなかった。 (edited)
Avatar
omochimetaru 11/6/2018 6:45 AM
ん〜 Mirror でも出てこないですね、 static property
Avatar
class C { static var FOO: Int { return 1 } static let BAR: Int = 1 } public func getFoo() -> Int { return C.FOO } public func getBar() -> Int { return C.BAR }
Avatar
diff let.ll var.ll. GitHub Gist: instantly share code, notes, and snippets.
Avatar
; Function Attrs: norecurse nounwind readnone define swiftcc i64 @"$S4test6getFooSiyF"() #0 { entry: ret i64 1 } ; Function Attrs: norecurse nounwind readnone define swiftcc i64 @"$S4test6getBarSiyF"() #0 { entry: ret i64 1 }
Avatar
最適化オプションは -O
6:47 AM
@rintaro そこはそうなっても、 BAR のストレージが残ってる可能性はありますよね? (edited)
Avatar
ストレージは残りますね。
Avatar
omochimetaru 11/6/2018 6:49 AM
S1a3FooV3barSivpZ
6:49 AM
↑これがストレージっぽい。
Avatar
ということは @noppe さんのケースでは、 let でも var でも最適化で実行効率は変わらないけど、メモリ効率は var の方が良いって結論で良いんでしょうか?
❤ 1
Avatar
omochimetaru 11/6/2018 6:50 AM
LLVM-IRの時点では少なくとも残ってますね
❤ 1
6:50 AM
その先で消える可能性はまだあります。
Avatar
なるほど。
Avatar
assembly でも残ってるので、残ると思いますよ。
Avatar
これって Int だから var でもいいけど、イニシャライザ呼んでたりすると var だと効率悪いですよね。値型で単純に引数をプロパティに格納するくらいのイニシャライザなら、それもインライン化されたら変わらない? (edited)
Avatar
omochimetaru 11/6/2018 6:53 AM
_$S1a3FooV3barSivpZ: .quad 42
Avatar
参照型絡むと、そもそも意味が違ってくるので、使い分けする必要がありますね。 (edited)
Avatar
値型で、値型のプロパティしか持たないケースですね。メンバーの葉まで全部値。
6:55 AM
イニシャライザで特殊な処理は存在せず、全部ただ引数をプロパティに入れてるだけ。
Avatar
omochimetaru 11/6/2018 7:00 AM
最適化を考えない場合は initに引数を渡して呼び出してstored propertyにコピー、その後完成したオブジェクトをreturnだから、 構築分のオーバーヘッドがあると思います 最適化を考えた場合はインライン化されて同じだと思います
Avatar
全部 インライン化できるかどうかでしょうね。最適化でインライン化できるなら computed property のほうがメモリ的に有利だとは思います。
7:02 AM
あと、static let の不利な点としては、lazy 扱いなのでコンパイラの判断によって、アクセスの度に初期化済みか否かの分岐が入る可能性がある、はず。 (edited)
Avatar
omochimetaru 11/6/2018 7:04 AM
define hidden swiftcc i8* @"$S1a3FooV3barSivau"() #0 { entry: %0 = load i64, i64* @globalinit_33_EFF83A1F47B777EA672D48C97C71346F_token0, align 8 %1 = icmp eq i64 %0, -1 br i1 %1, label %once_done, label %once_not_done once_not_done: ; preds = %entry call void @swift_once(i64* @globalinit_33_EFF83A1F47B777EA672D48C97C71346F_token0, i8* bitcast (void ()* @globalinit_33_EFF83A1F47B777EA672D48C97C71346F_func0 to i8*), i8* undef) br label %once_done once_done: ; preds = %once_not_done, %entry %2 = load i64, i64* @globalinit_33_EFF83A1F47B777EA672D48C97C71346F_token0, align 8 %3 = icmp eq i64 %2, -1 call void @llvm.assume(i1 %3) ret i8* bitcast (%TSi* @"$S1a3FooV3barSivpZ" to i8*) }
7:04 AM
↑-Ononeでの、その分岐
7:05 AM
@"$S1a3FooV3barSivpZ" = hidden global %TSi <{ i64 42 }>, align 8 define hidden swiftcc i8* @"$S1a3FooV3barSivau"() local_unnamed_addr #0 { entry: ret i8* bitcast (%TSi* @"$S1a3FooV3barSivpZ" to i8*) }
7:05 AM
↑-Oでその分岐の削除
7:06 AM
ストレージの初期値をLLVMのconstantにできるなら分岐削除できるっぽいから
7:06 AM
koherの言ってる完全struct treeなら
7:06 AM
消えそう。
7:08 AM
でもその場合はインライン化もされそうだな、インライン化はされないけど同期は消える場合はどういうのだろ、モジュール跨ぎ?
Avatar
@inlinable ってプロパティには付けられないっけ? (edited)
Avatar
モジュール跨いだら、イニシャライザに副作用があるかの判断ができないから、同期せざるを得ない気がします。
Avatar
イニシャライザも全部 @inlineable 想定で。
Avatar
omochimetaru 11/6/2018 7:09 AM
あ、またぐのは Cat.foo を呼び出す側で、 Cat.foo の初期化は Catのあるモジュールのビルド時に完結しますよね
7:10 AM
inlineableは
7:10 AM
インライン化することを保証しなくないです?
Avatar
保証しないのはモジュール内も同じじゃない?
Avatar
omochimetaru 11/6/2018 7:11 AM
インライン化しない場合の話だから
7:11 AM
@inlineableをつけなければ、しないかも。
7:12 AM
class Cat { static let a: Int = 42 } にたいして、Cat.aのgetter関数が生成されていて、同期ロジックはgetterの内部で作られていて
Avatar
ああ、分岐が消えるか消えないかについてか。
Avatar
omochimetaru 11/6/2018 7:13 AM
Catと違うモジュールにあるコードから Cat.a を読むコードを書いた場合
7:18 AM
Cat.aの関数呼び出しをして、でもその先では同期が無い
7:18 AM
って状態になるかなあと。
Avatar
メモリ的にはcomputed propertyにしたいところですが、staticに宣言しようとしているところがOpenGLESのGLenum周りなので効率もきになるところです 🤔 と言っても1drawあたりで20~30コールくらいなので結局computed propertyで宣言しちゃおうと思います!ありがとうございます 😄
Avatar
omochimetaru 11/7/2018 7:12 AM
@hiragram public protocol DecodableByJSON : Decodable { associatedtype JSON : Decodable init(from json: JSON) throws } extension DecodableByJSON { public init(from decoder: Decoder) throws { let json = try JSON(from: decoder) try self.init(from: json) } } public struct GenericVector3<T> { public var x: T public var y: T public var z: T public init(_ x: T, _ y: T, _ z: T) { self.x = x self.y = y self.z = z } } public typealias GenericVector3JSON<T> = Array<T> extension GenericVector3 : DecodableByJSON /*(これが必要) , Decodable*/ where T : Decodable { public typealias JSON = GenericVector3JSON<T> public init(from json: GenericVector3JSON<T>) throws { guard json.count == 3 else { fatalError() } self.init(json[0], json[1], json[2]) } }
7:13 AM
ConditionalConformanceでは間接的にProtocolを適用できないんですね (ここでは「DecodableByJSONを満たさせると自動的にDecodableを満たす」ことを指して「間接的」と呼んだ
Avatar
それどういうエラーになる?
Avatar
omochimetaru 11/7/2018 7:15 AM
#swiftbot-sandbox でbotに投げたらいいじゃない。 (edited)
Avatar
Codable系はそもそもextensionから付けられないみたいな制約があるのでcondconf一般の話なのかCodableの話なのか判別つかないなう
Avatar
omochimetaru 11/7/2018 7:16 AM
なるほど?
7:16 AM
Codable系はそもそもextensionから付けられない
それ自体はでも今はできるよ。Swift4.2で入った。
(edited)
Avatar
decodeなどのメソッドを生成するときにextensionだと困るみたいなエラーでない?
7:16 AM
へー入ったのか
Avatar
fixitの差し込むコード面白いなw
7:26 AM
初めてみたw
Avatar
omochimetaru 11/7/2018 7:30 AM
2択でDecodableのextensionが産まれるんだけど
7:31 AM
そのFixItをベースにしてもコードを完成させられなくて
7:31 AM
: DecodableByJSON のところを : DecodableByJSON, Decodable とするのが正解
Avatar
redundant conformanceでないのかそれ
Avatar
omochimetaru 11/7/2018 7:32 AM
ConditionalConformanceでは間接的にProtocolを適用できない、というか、しない、っぽい?
Avatar
Swiftで書かれたクラスのdeinitが呼ばれるタイミングってSwiftから使ったときとObjective-Cから使ったときで変わったりしますか?
Avatar
omochimetaru 11/7/2018 9:30 AM
変わらないと思うけどObjCのオブジェクトはAutoReleasePoolで解放される場合があるのでそういうのから参照されてるとARPoolのdrainのタイミングまで遅延する場合がありそうです
Avatar
あーなるほど。それはありそうですね
9:31 AM
SwiftってAutoReleasePoolないんですか?
9:32 AM
Swiftから書ける autoreleasepool {} はあれ完全にObjC用なのでしょうか
Avatar
omochimetaru 11/7/2018 9:32 AM
無いはず・・・
9:33 AM
あれはFoundationで定義される関数です
9:33 AM
フルネームだと ObjectiveC.autoreleasepool っぽい。
Avatar
思いっきりObjectiveCの中に入ってましたね。
Avatar
omochimetaru 11/7/2018 9:35 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
すごくObjC用っぽい
9:37 AM
とりあえずタイミング違う可能性ありそうなのがわかってすっきりしました。ありがとうございます
🙂 1
Avatar
omochimetaru 11/7/2018 9:38 AM
調べたいオブジェクトがわかってるなら、deinitを書いてそこにブレークポイントを貼るとわかりやすいかもしれません。
Avatar
The review of SE-0235 - Add Result to the Standard Library begins now and runs through November 12, 2018. 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 priva...
Avatar
Swift.ErrorはExtension with Generic Where Clauseで。 public enum Result<Value, Error> { case success(Value), failure(Error) // … } extension Result where Error: Swift.Error { /*…*/ } extension Result where Error == Swift.Error { /*…*/ } https://github.com/apple/swift-evolution/blob/master/proposals/0235-add-result.md#detailed-design (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
来ましたね大物が
12:02 AM
ていうか今回も起きたらすでに野村速報が投稿済みw
12:07 AM
プロポーザル書けるほど話し合いまとまってたんですね
Avatar
プロポーザル読んだ Error == Swift.Error の場合がExistentialとしてのエラー型の場合で、 こっちを使えばエラー型を指定しない場合としても使えるのかな
12:57 AM
Antitypicalとはちょいちょいメソッド名が違いますね
1:00 AM
スラバがサラッとでかいこと言ってるw
Since Error existentials have a single retainable pointer representation, we should consider making Error self-conforming. As a bonus, in Chris's implementation the extension Result where Self.Error == Error can be merged with extension Result where Self.Error : Error.
1:01 AM
Existentialがそれ自身をconformしない仕様に切り込んでいる・・・
Avatar
をー
1:39 AM
Result<T> vs Result<T, E>紛争が終結してる
Avatar
omochimetaru 11/8/2018 1:40 AM
両方サポートできていいですよね。
Avatar
昔 Chris Lattner が、 typed throws をサポートするか決着を付けないと Result の話はできないって繰り返し言ってたから無視してたんだけど、 Proposal まで作ったのか。
1:45 AM
現段階では時期尚早な気がする。
Avatar
omochimetaru 11/8/2018 1:53 AM
そうですね。レビューマネージャがそのラトナー自身なのでちょっとびっくり。 (edited)
Avatar
レビューマネージャーは適当に割り振られてるんじゃない?
1:56 AM
賛成とかじゃないと思う。
2:00 AM
非同期処理の多くは async/await で解決できるし、 "Delayed Handling" はむしろやらない方がいいケースが多いからやらざるを得ないときだけがんばればいいと思うし、 "Separating Errors" は例が抽象的すぎてこれがやりたいことが頻発するイメージがわかない。
Avatar
omochimetaru 11/8/2018 2:02 AM
そういう趣旨の反対コメントもありますねえ
Avatar
dataTask については、戻り値を URLSessionDataTask に使ってるのが微妙だけど、これは Foundation の API 設計の問題だと思うなぁ。
2:06 AM
response をエラーケースでも受け取りたいとしても、 dataresponseerror を受け取るだけなら↓ async/await と typed throws で↓にできる。 func dataTask(with url: URL) async throws URLSessionDataTaskError -> (Data, URLResponse) { ... } struct URLSessionDataTaskError: Error { let response: URLResponse? }
2:08 AM
以前 Joe Groff が Result 全否定してたときのコメント。 Yeah, we extensively discussed adding a Result type internally, but ultimately couldn't justify it. The only real use case we could see in the wild was for threading errors through CPS-inversion-style abstractions like async promises, something we hope to provide proper language support for. More generally, expressing effects as monadic values is a pretty awful abstraction; aside from polluting the Internet with an endless deluge of unhelpful tutorials, they also don't compose cleanly, they impose nesting where is desired—you have to pick between Result<Async<T>> and Async<Result<T>>, or build ResultT<AsyncT<Identity>><T> out of monad transformers—and they don't do the natural thing when used with other higher-order abstractions—if you're mapping a `throws` function over a collection, you probably want to propagate that error like `rethrows` does, not end up with a collection of Result<T>. I'd rather see us adopt an extensible algebraic effects system, something like http://www.eff-lang.org , which provides a framework for `throws`, `async` and other control flow effects to be cleanly composed and abstracted over. I see `throws` as the first seed of that. https://forums.swift.org/t/throws-as-returning-a-result/1799/2
Yeah, we extensively discussed adding a Result type internally, but ultimately couldn't justify it. The only real use case we could see in the wild was for threading errors through CPS-inversion-style abstractions like async promises, something we hope to provide proper langu...
Avatar
omochimetaru 11/8/2018 2:21 AM
It's not quite that cut and dry. As soon as you have more than one thing with this sugar, you get composition issues—is () throws async -> () a Result> or a Future>? More likely what you want when you're inside the context is to have a set of "effects" rather than a nesting...
2:22 AM
JoeGroff書き込んでここでも「エフェクトが欲しいんじゃないの?」って書いてる?
2:23 AM
Like much of the proposed API here, though, it's probably best to consider that additively once we get the basic type in place.
ここが読解できないんですけど、Resultを入れるんじゃなくてAPIごとにenumでも定義したら?って意味です?
(edited)
Avatar
omochimetaru 11/8/2018 3:17 AM
雑にまとめたら良く伸びました https://twitter.com/omochimetaru/status/1060348871698657280
クランチに記事を投稿しました SwiftにResult型が提案されレビュー入りした https://t.co/vvAF2RzVSP #qrunch
Avatar
そういえば、Existentialがそれ自身のプロトコルには準拠しない、っていうやつの理由は何なんでしょう?
Avatar
本当はopening existentialをしないとfunction群は使えないはずだけど、swiftはそこの記法を省略してるだけみたいな感じ
Avatar
I disagree to add Result to the standard library for now. Major use cases of Result are error handling of asynchronous operations. We will be able to do it without Result when Swift supports async/await. // without Result nor async/await func download(from url: URL, _ c...
Avatar
omochimetaru 11/8/2018 4:08 AM
スレ伸びるの早いですね
Avatar
omochimetaru 11/8/2018 4:23 AM
@koher と同様に非同期が先って意見や、Optionalの言語サポート(?.とか)みたいなResultの言語サポートを無視して型だけ入れる話を先にするのは良くないとか、結構反対もある
Avatar
少なくともこのまま入ることはないんじゃないかな。 Result 入れるにしてもどんな API 付けるかだけでも相当議論の余地があるはず。
Avatar
omochimetaru 11/8/2018 4:25 AM
入れるにしてもどんな API 付けるかだけ
そこについてはPitchスレがめっちゃ伸びてたんでそっちでやってるのかと思ってました。
(edited)
4:26 AM
でもこの流れを見てると、正規プロポーザル出てから本気出す人も結構居るんですね。
Avatar
Proposal は Forum で議論すれば盛り上がってなくても出せるし、 Proposal 出てからが本番なのでは。
Avatar
omochimetaru 11/8/2018 4:28 AM
Forumで議論しなかったProposalは当然そうだけど、長いこと書き込まれてたPitchに関しては、関心のある人は書き込むと思ってた。
Avatar
Proposal の Review が最後の砦なので、そこだけ見てる人も多そう。
Avatar
omochimetaru 11/8/2018 4:29 AM
文書化されていちどまとまるから入りやすいというのはあるか。
4:29 AM
スレ長すぎてわかんないもんなあ。
4:29 AM
最後の砦
なるほど
4:30 AM
そういう意味では、自分でプロポーザルかける程度にPitchが温まったら、さっさとレビュー出したほうが
4:30 AM
意見の回収効率が良くて良さそうだ。
4:31 AM
いや、難しいな、文書化するのにコストがかかるから、そこにジレンマがあるのか。
Avatar
Result ほんと最近は↓さえあれば十分なんじゃないかと思ってる。 enum Result<Value> { case success(Value), failure(Error) func get() throws -> Value { ... } }
4:33 AM
throws/try でうまく書けないところで使うだけだから、すぐに getthrows/try の世界に戻して言語機能を活用した方がコードがシンプルになることが多い気がする。
4:34 AM
あとは Result { try foo() } ができるようにするイニシャライザを付けるくらい。
Avatar
omochimetaru 11/8/2018 4:39 AM
言語機能の方だとflatMapErrorとかは書きにくくないですか?
4:40 AM
あ、Untyped Errorなら、flatMapErrorはいらないか。
4:42 AM
非同期のところに関しては確かにそうですね. do { try get() } catch { } したいだけがほとんどだ (edited)
Avatar
@omochimetaru
ここが読解できないんですけど、Resultを入れるんじゃなくてAPIごとにenumでも定義したら?って意味です?
よくわかんないけど、まずは最小限の Result を加えてから API の追加を検討する話をしてんのかな??
Avatar
omochimetaru 11/8/2018 7:21 AM
Like much of the proposed API here
ここはResult型のメソッドのことか。
7:22 AM
例に出てくるNSURLSessionとかのことかと思った。
Avatar
うーん、ドキュメントみたいなフォーマルな文章は読めても、こういうくだけた英文になると急に難易度上がるね・・・。多分その前の文が
I think it would nonetheless behoove us to integrate Result better into the language; if nothing else, it would be great to extend ?, ?? and other optional-related operators to also work with Result.
で、ほしいのはエフェクトのセットで Result とか Future はモナド変換の複雑さを抱えてて微妙だけど、にも関わらず標準ライブラリへの追加を望むのであれば、 Result のための ??. で使う ? のこと?)や ?? があった方がいいだろうね、ということを言ってると思うので、そういう風に続くのが自然かなと思った。
Avatar
omochimetaru 11/8/2018 7:32 AM
なるほど
Avatar
+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, 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. While we should definitely have helper operations to map back and forth between throws and Result when the failure type of Result conforms to Error, I think Result would be maximally useful if it doesn't need to be used as an integrated facet of the throws-based error handling mechanism. 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:48 PM
↓のような理解でいいのかな? throwsResult は異なる問題を取り扱ってて、 throw されたエラーは伝播して問題の発生源から遠く離れたところでハンドリングされるから typed じゃなくてゆるく Error として扱えば良くて、 Result は( Optional のように)即時ハンドリングされることが意図されてるから明確な型を指定できるのが適する。 throwsResult を相互変換できる機能は提供すべきだけど、 throws とは別の局面で使われてこそ Result は真価を発揮すると思う。 (edited)
😀 1
Avatar
前に @koher が同じこと書いてた気がしますけど public enum VectorizateNoAccelerate {} #if !canImport(Accelerete) && !NO_ACCELERATE public enum Vectorizate {} #else public typealias Vectorize = VectorizateNoAccelerate #endif でNO_ACCELERATE有効で外部からVectorizate.staticMethodで呼ぼうとするとパッケージ名のVectorizateの方を参照してしまって詰んだ…… (edited)
8:53 AM
結局パッケージ名か型名変えて対応したんでしたっけ?
Avatar
シンボル名インポートする裏技?がある
Avatar
インポート側で対応ってことですか? 公開するライブラリとして作ってるのでそれだと微妙ですね……
Avatar
そうだね、インポートする側の技
Avatar
As recently announced by @akyrtzi, we have been working on a new language service for Swift and C-family languages based on the Language Server Protocol (LSP). I am excited to say that the source code for SourceKit-LSP is now available on GitHub! While the new language servi...
🎉 5
Avatar
Language Server Protocol implementation for Swift and C-family - apple/sourcekit-lsp
2:15 AM
おおおお
2:19 AM
VSCodeとSublimeTextで試せる状態みたいですね
Avatar
ですね。VSCodeの場合はそれ用のプラグインをビルドする必要があるのでちょっと面倒。
Avatar
AppCode民も幸せになるかしら
Avatar
AppCode は LSP 対応してないと思います
Avatar
IDEAはやってませんでしたっけ
2:35 AM
プラグインだった
Avatar
おお
Avatar
swift-4.2.1-RELEASEでビルドしても、普通に動くぽい。
3:04 AM
Visual Studio Code - insidersで。
Avatar
型が見えてる!
Avatar
func foo<T: P>(_: T) extension P { func _forwardToFoo() { foo(self) } } func callFooOnEach(_ ps: [P]) { for p in ps { p._forwardToFoo() } }
3:36 AM
PのExisはP自身にconformしないが、extensionの中のselfを介してconformさせられる技
3:37 AM
It's awkward, but you can in fact "open" the existential by invoking a protocol extension method, which will give you Self as the dynamic type of the value inside the method, which you can then pass to generic functions: func foo(_: T) extension P { func _forwardToFoo() {...
3:37 AM
↑existensialのassoctype制約を無くすピッチ
3:39 AM
昔々から今までできなかったのは技術的な理由で、PWTがassoctypeを持ってなかったからで、今はそこがクリアされてる らしい
Avatar
これいつから出来るようになったの
5:25 AM
昔試して死んだ記憶がある
5:26 AM
いや、これじゃなかったかな
Avatar
Most of the foundation for this was laid in earlier patches. This PR should not be merged because it arguably requires Evolution approval. PRs this depends on that aren't in the 5.0 branch: #20...
2:19 AM
let errorValue: Error = MyError.reallyImportant("goodbye") func castValueToError<T>(error: T) -> Error? { return error as? Error } // CHECK-NEXT: reallyImportant("goodbye") print(castValueToError(error: errorValue) ?? value)
2:20 AM
自己confromただしErrorだけ、という謎パッチ
😩 1
🤔 1
Avatar
November 16, 2018 (final branching)
7:03 AM
そういえば5.0final branchingが終わったのか
Avatar
お、無事 @dynamicCallable が final branching 前にマージされてる。 https://github.com/apple/swift/pull/20305 (edited)
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
5.0の大きな特徴の1つになりそうですね
Avatar
うれしい。
Avatar
import Foundation class Cat { @objc func nya() -> Int { return 3 } } class Dog { @objc func wan() -> Int { return 4 } } func f(_ a: AnyObject) { let x = a.nya() let y = a.wan?() print(type(of: x), x) // Int 3 print(type(of: y), y) // Optional<Int> nil } f(Cat())
7:26 AM
こんなんあるんですね・・・
Avatar
なんで AnyObjecta.nya() できるの?
7:44 AM
@objcがついているメソッドはAnyObjectに対して呼び出せるんです。 (edited)
Avatar
あー、 REPL に分割して貼ったからエラーになったのか。
7:47 AM
REPL に↓のように分割してコピペするとエラーになる。 import Foundation class Cat { @objc func nya() -> Int { return 3 } } class Dog { @objc func wan() -> Int { return 4 } } func f(_ a: AnyObject) { let x = a.nya() let y = a.wan?() print(type(of: x), x) // Int 3 print(type(of: y), y) // Optional<Int> nil } f(Cat()) let a: AnyObject = Cat() a.nya()
Avatar
ほんとだ。なんで?
Avatar
REPL のネームスペース(?)いまいちよく理解してないんだけど、実行単位ごとに名前空間が変なんよね。
Avatar
なるほど。
7:49 AM
LLVM的にはModuleっていう単位が構築されてるので
7:49 AM
あり得ると思います。
Avatar
同じ名前を使えたり。実行単位ごとに名前空間が切られてる?その割にはまたいでアクセスできたりするし、よくわからない。 (edited)
Avatar
Swift的には、REPLのモジュールと、1コマンドごとのサブモジュールになってるのかな
Avatar
@objcがついているメソッドはAnyObjectに対して呼び出せるんです。
↓これできるの気持ち悪い・・・。 import Foundation class Foo {} let a: AnyObject = Foo() print(String(describing: a.lowercased)) // nil
Avatar
何がどうなってるんだ
7:59 AM
メソッドがなければunrecognized selectorで落ちるはず・・・
Avatar
NSString@objclowercased というプロパティがあるからまずコンパイルは通る。
8:00 AM
a.lowercased の結果が nil になるのはよくわからない。
8:01 AM
この @objc な API は呼び出せるの、 Swift でできる必要あったのかなぁ。今となっては @dynamicMemberLookup@dynamicCallable でできるとキレイそうだ。
Avatar
もしかして
8:01 AM
メソッドの場合は () と ?() が使えるように
Avatar
unrecognized selector ではなく
Avatar
プロパティの場合だから
Avatar
nil になる仕様なら
Avatar
生えてなければnilなのか
Avatar
wan?() は普通の挙動だね。
8:03 AM
a.wannil になって、 nil に対するコールで ?()nil を返してる?
8:05 AM
import Foundation class Cat { @objc func nya() -> Int { return 3 } } class Dog { @objc func wan() -> Int { return 4 } } func f(_ a: AnyObject) { let x = a.nya() let y = a.wan print(type(of: x), x) print(type(of: y), y) } f(Cat()) Int 3 Optional<() -> Int> nil (edited)
8:09 AM
↓だと型が定まらなくてコンパイルエラー。 import Foundation class Cat { @objc func nya() -> Int { return 3 } } class Dog { @objc func wan() -> Int { return 4 } } class Foo { @objc func wan() -> Double { return 5 } } func f(_ a: AnyObject) { let x = a.nya() let y = a.wan print(type(of: x), x) print(type(of: y), y) } f(Cat()) wan-nya-dynamic.swift:15:13: error: ambiguous use of 'wan()' let y = a.wan ^ wan-nya-dynamic.swift:7:16: note: found this candidate @objc func wan() -> Int { return 4 } ^ wan-nya-dynamic.swift:10:16: note: found this candidate @objc func wan() -> Double { return 5 } ^
Avatar
なるほど
Avatar
z がヤバイことにwww import Foundation class Cat { @objc func nya() -> Int { return 3 } } class Dog { @objc func wan() -> Int { return 4 } } class Foo { @objc func wan() -> Double { return 5 } } func f(_ a: AnyObject) { let x = a.nya?() let y: Int? = a.wan?() let z: Double? = a.wan?() print(type(of: x), x) print(type(of: y), y) print(type(of: z), z) } f(Dog()) Optional<Int> nil Optional<Int> Optional(4) Optional<Double> Optional(1.385238852664656e-309)
8:13 AM
メモリレイアウトの違う二つの値だったらどうなるんだ?
Avatar
ObjCのメソッドがないときのDoubleが0になる挙動・・・?
8:14 AM
いや、メソッドがないならnilか。なんだこれ。 (edited)
8:14 AM
Intの4をDoubleとしてbitcastしちゃってるのか。
Avatar
うん、おそらく。
8:16 AM
32 bit が 64 bit になった🤔 import Foundation class Cat { @objc func nya() -> Int { return 3 } } class Dog { @objc func wan() -> Int32 { return 4 } } class Foo { @objc func wan() -> Double { return 5 } } func f(_ a: AnyObject) { let x = a.nya?() let y: Int32? = a.wan?() let z: Double? = a.wan?() print(type(of: x), x) print(type(of: y), y) print(type(of: z), z) } f(Dog()) Optional<Int> nil Optional<Int32> Optional(4) Optional<Double> Optional(3.22526e-319)
8:20 AM
↓死んだ。 import Foundation class Cat { @objc func nya() -> Int { return 3 } } class Dog { @objc func wan() -> Int { return 4 } } class Foo { @objc func wan() -> X { return X(value: 5) } } @objc class X: NSObject { var value: Int init(value: Int) { self.value = value } } func f(_ a: AnyObject) { let x = a.nya?() let y: Int? = a.wan?() let z: X? = a.wan?() print(type(of: x), x) print(type(of: y), y) print(type(of: z), z) } f(Dog()) Segmentation fault: 11
Avatar
プロパティアクセスは 同名のメソッドの呼び出しに変換されてさらに呼び出す前にrespondsToSelector:でチェックしてますね
12:15 PM
nya() も wan() も呼び出す前にrespondsToSelector:でチェックしてますね
12:20 PM
プロパティアクセスではないですね。どっちもローレベルで見るとメソッドだ
Avatar
@objc funcはObjcランタイムで動くようになるし、AnyObjectはFoundation importしたら実質NSObjectになるから
12:22 PM
凡ゆるメソッドが呼び出せる、idになる
Avatar
nyaとwanに関しては、 .nya?() で呼び出さないと、なかった場合はunrecognized selectorといってクラッシュしました
Avatar
そう、?をつける
Avatar
メソッドの型が IUO になっているような感じ。
Avatar
objc protocolのoptional funcと同じ
12:23 PM
ObjectiveCだと、id型に対してなんでもメソッド呼び出せた(クラッシュしないとは言ってない)のと一緒ですね
Avatar
notRecogonizedで死なないようにrespondsToSelectorを挟むSwift優しい(優しくはない
Avatar
ObjC Runtimeも内部的には検査はしているのではないですか?
12:28 PM
えいやで呼び出してるわけではなく。
12:28 PM
というか関数ポインタをvtableから探してこないといけないからそこで検出されそう。
Avatar
vtableじゃなくて
12:28 PM
なんだったかな、objcはvtableではない
Avatar
-doesNotRecognizeSelector:というメソッドが呼ばれて何もしなければ死ぬ
Avatar
たしかにいわゆるvtableでは無理か。
12:31 PM
selectorとclassのピアからmethodを引いて、そのmethodが関数へのポインタを持ってるみたいな感じ、だったはず
12:32 PM
所謂method swizzlingは、selectorとclassのピアに挟まってるmethodを差し替えるテクニックのこと
Avatar
doesNotRecognizeSelectorをオーバーライドすると死なないやつもできるんか・・・
Avatar
内部的なチェック機構は詳しく無いのだけど、methodが見つからなければdoesnotやって処理されなければunrecognizedで死
12:33 PM
事前チェックのためにrespondsToがある
12:34 PM
swiftのnya?()は、意味的にはrespondsTo(nya)→nya()だと思う
12:34 PM
RxSwiftで死を回避してるコードあった気がする
Avatar
mport Foundation class Cat { @objc dynamic func respondsToSelector(_ sel: Selector) -> Bool { return true } } let c: AnyObject = Cat() c.lowercased
Avatar
なんてことを
Avatar
Unrecognized selectorで死んだ
Avatar
Kishikawa Katsumi 11/27/2018 12:54 PM
ObjCの話だと https://developer.apple.com/documentation/objectivec/nsobject/1571960-methodsignatureforselector?language=objc https://developer.apple.com/documentation/objectivec/nsobject/1571955-forwardinvocation?language=objc methodSignatureForSelector: と forwardInvocation: の組み合わせでRailsみたいに完全に動的なメソッドやプロパティの呼び出しに対応することもできるよ。
😎 1
Avatar
respondsToSelectorをオーバーライドしたらobjcのメッセージ探索フェーズに入れる事が分かったのでやろうと思えばSwiftでもできますね
1:01 PM
やらないけど
Avatar
forwardInvocationもありましたね、RxSwiftに入ってるのはそっちだった気がする
Avatar
public class Animal { public init() {} } func main() { // OK _ = Animal() // OK _ = Animal.init() // OK _ = Animal.self.init() // error: Constructing an object of class type 'Animal' with a metatype value must use a 'required' initializer _ = (Animal.self as Animal.Type).init() }
2:49 AM
↑面白い。 式「Animal.self」の型は「Animal.Type」だと思っていたけど、 Animal.selfは { K ; K == Animal.Type } で、 Animal.Typeは { K ; K <= Animal.Type } であって、 型システム上の区別があるようだ
2:51 AM
一度ダイナミックなメタタイプになってしまうと、サブタイプのメタタイプが入る可能性があって、意味が変わる。 (edited)
Avatar
なるほど。↓でも同じことになるね。 let animalType = Animal.self _ = animalType.init()
2:56 AM
あと、 Animalfinal 付けてもコンパイル通る。
Avatar
finalなるほど
Avatar
あと当たり前だけど initrequired 付けても通る。
Avatar
そうですね。required init はSwiftにおいて理解するのが結構難しい概念だと思う
Avatar
async/awaitのキャンセルについての提案が投稿されてたので、 スレ違いだけど最近考えてたキャンセルサポートの方法を書き込んでみた。
3:17 AM
I want to share my idea to you. First, without any support about cancellation for async/await, user can use pattern as like below. // cancel notification sender interface class CancelContext { var token: CancelToken func cancel() } // cancel notification receiver interf...
Avatar
ジョーグロフから、それ考慮済みだよ、ってコメント来た!😅 でも考慮済みなら良かった。
Avatar
# This library is only hypothetical, sorry from cancel_tokens import cancel_after, cancel_on_callback # Returns an opaque CancelToken object that enters the "cancelled" # state after 10 seconds. cancel_token = cancel_after(10) # So this request gives up after 10 seconds requests.get("https://...", cancel_token=cancel_token) # Returns an opaque CancelToken object that enters the "cancelled" # state when the given callback is called. cancel_callback, cancel_token = cancel_on_callback() # Arrange for the callback to be called if someone clicks "stop" stop_button.on_press = cancel_callback # So this request gives up if someone clicks 'stop' requests.get("https://...", cancel_token=cancel_token) https://vorpus.org/blog/timeouts-and-cancellation-for-humans/ (edited)
4:33 AM
Joe Groff が挙げてる方式。(斜め読みでコード抜き出しただけなので本当にこれが言いたいのかわからないけど。) (edited)
4:34 AM
トークンとコールバックが別で扱われてるのがちょっと気持ち悪い気がする。
4:40 AM
↓みたいな方がいい気がする。 struct Canceller { func cancel() func onCancel(_ body: () -> Void) } func download(from url: URL, canceller: Canceller? = nil) async throws -> Data let canceller = Canceller() let data = try await download(from: url, canceller: canceller) DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) { canceller.cancel() } stopButton.onTap { canceller.cancel() }
4:41 AM
よくみたら @omochimetaru 案とほぼ同じ気がする・・・。
4:41 AM
ちがうか。
4:44 AM
↑の Canceller だと context と token の役割が一体化していて、 canceller に onCancel ができるのがまずいのか。
4:49 AM
外部に公開するときに純粋に cancel の機能だけを公開したい。
4:50 AM
でも外部から Canceller を注入するなら、一体化しててまずいことってあるかな?
Avatar
非同期関数の内部でcancelを呼ばれないようにしたい。
Avatar
そっち側の要求もあるのか。 API 利用者視点しか考えてなかった。
5:43 AM
@omochimetaru ↓は利用者側が context から token 取り出して register できるのは問題ない? // cancel notification sender interface class CancelContext { var token: CancelToken func cancel() } // cancel notification receiver interface class CancelToken { func register(handler: @escaping () -> Void) }
Avatar
それは問題ないですね、むしろやりたい可能性がある
5:43 AM
並行発火するタスクをその場でアドホックにクロージャーだけで書いたりできる。
Avatar
うーん、↓みたいな API の視点で考えると Canceller に対して利用者がキャンセル時の挙動を登録できるのは気持ち悪い気がする。 func download(from url: URL, completion: (Result<Data, Error>) -> Void) -> Canceller
5:49 AM
並行発火するタスクをその場でアドホックにクロージャーだけで書いたりできる。
cancel を呼び出す側が必ず存在するので、そこに記述すれば良かったりしない?
Avatar
それは場合によりそうですけど、局所性が下がって読みづらくなることがありそう
Avatar
逆に、 API 側が何らかの都合で自己キャンセルはあり得ないのかな?
Avatar
それはあり得るのでやったら良いです
5:50 AM
例えばネットワークが切断してしまうのと
5:50 AM
APIの利用側から見れば同じです(意図せず中断するという意味で
Avatar
じゃあ cancel を呼べてまずい理由はないのでは?
Avatar
スコープが違います
5:52 AM
タスクが自殺するのはそのタスクだけの話で
5:52 AM
Cancellerでやりたいのは複数の合成したタスク全体を全部止めたい話
Avatar
一つの Canceller を複数の処理に与えてまとめてキャンセルするときに内部からキャンセルされたら困るのか
Avatar
そうです
Avatar
で、 cancel が複数箇所で行われうるときに、 Canceller 経由で register できないと cancel を書く度に同じ処理を記述しないといけないのか。
Avatar
? 文意が取れない
Avatar
canceller.token.register { // キャンセル時の処理 } ... func pressStopButton(_ sender: UIButton) { canceller.cancel() } と書くよりも func pressStopButton(_ sender: UIButton) { canceller.cancel() // キャンセル時の処理 } の方がいいかと思ったけど、 canceller.token.register { // キャンセル時の処理 } ... func pressStopButton(_ sender: UIButton) { canceller.cancel() } func doubleTap(_ gestureRecogizer: UITapGestureRecognizer) { canceller.cancel() } みたいなときはキャンセル時に差し込む処理がまとめて書ける?
Avatar
ああ、そういう意味か。 それもそうだし、 self.canceller が対応してる非同期タスクが、2種類あるかもしれない。
6:05 AM
ButtonAを押して発火する動画のDL処理と、ButtonBを押して発火する動画のアップロード処理があるとして、 どっちの場合も同じcanceller propertyで使っているかも。(これらの処理は同時には生じないとする
6:05 AM
そのとき、今起きてる処理に対応するキャンセル処理っていうのは、Cancellerオブジェクトにぶら下がってないといけない。
Avatar
なるほど。キャンセルしたときに何が起こるかは canceller に依存していて、そのためには canceller に登録処理を行えないといけないのか。
6:09 AM
そういう意味だと cancel_callback, cancel_token = cancel_on_callback()callbacktoken の両方を取り回さないといけないことになって良くないんじゃない?
Avatar
そのcancel_callbackとcancel_tokenを、cancelContext.cancel() と cancelContext.token にまとめてるのが僕の(というかC#の)書いてる案で
6:10 AM
そのpythonのやつがなんでそれをペアタプルで返したのかはよくわかんないですけど
6:11 AM
プログラミングインターフェースの観点からいけば、その段階は記事の中盤なので
6:11 AM
終盤ではwithで隠蔽してるからそこは論点の本質じゃないと思います (edited)
Avatar
たしかに "Cancel tokens are unreliable in practice because humans are lazy" とか書かれてるな
6:14 AM
"Cancel scopes: Trio's human-friendly solution for timeouts and cancellation" が提案してる箇所か
Avatar
昼読んだときは Joe Groff の返信しかちゃんと見てなくてコンテクストを取り違えてたけど、 @omochimetaru の提案は非同期処理とキャンセルのトークンを暗黙的に(全体で見れば明示的だけど個々の API コールで見れば暗黙的に)結びつけたいということだったのか。で、 Joe Groff がリンクしてるのも with を使った同じような仕組みになってると。 (edited)
Avatar
そうです
10:09 AM
で、僕が言いたかったのはそれを実装するためには言語サポートで
10:09 AM
TLSにあたるもののコルーチン版が要るぞって話で (edited)
10:11 AM
ジョーグロフの回答で、それスレがあるよって言われたので解決
10:13 AM
スレッドの方では主に実行スレッドのコントロールについて話されてるけど、
10:13 AM
キャンセルに言及してる人も居て
10:13 AM
かつ、キャンセルのプログラミングインターフェースの観点では、そのブログの方で補完されてる
Avatar
norio_nomura 12/4/2018 2:14 AM
まだタグも無くswift.orgにも現れていませんがswift-5.0-DEVELOPMENT-SNAPSHOT-2018-12-03-aがダウンロード可能になってるぽいです。 (edited)
2:15 AM
dockerイメージ: norionomura/swift:swift-5.0-branch
Avatar
norio_nomura 12/4/2018 4:00 AM
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
Kishikawa Katsumi 12/4/2018 4:21 AM
私のPlaygroundもそろそろ更新しよう。 Swift 5っぽいソースコードを載せたいんですけど、何がそれっぽいですかねえ?
Avatar
@dynamicCallable ですかねー
Avatar
omochimetaru 12/4/2018 4:22 AM
SE-0216 Introduce user-defined dynamically "callable" types
4:22 AM
SE-0215 Conform Never to Equatable and Hashable
4:23 AM
https://apple.github.io/swift-evolution/ ↑ここで5.0の見てたけど、あまり大きいのは無い感じ
4:28 AM
String周りは結構変わってる気がする。
Avatar
omochimetaru 12/4/2018 4:28 AM
ああそうか
4:28 AM
#"This string has an \#(interpolated) item"#
4:29 AM
RawString入ったのは見た目にも変化があっていいですね
Avatar
Kishikawa Katsumi 12/4/2018 4:31 AM
^ これはわかりやすい!
4:32 AM
dynamicCallable も書いたらインパクトが強そうです。
Avatar
StringInterpolation 関係もうまく使えば便利になりそう。 extension String.StringInterpolation { mutating func appendInterpolation<T>(_ val: T?, default defaultValue: String) { if let val = val { appendInterpolation(val) } else { defaultValue.write(to: &self) } } } let value: Int? = nil print("The value is: \(value, default: "<nil>")")
Avatar
Kishikawa Katsumi 12/4/2018 4:41 AM
^ いいですね。採用で。
Avatar
omochimetaru 12/4/2018 4:42 AM
ああこれ、コンパイルの仕方が変わるだけじゃなくて、
4:42 AM
\() のオーバーロード?を自分で追加できるようになるんですね。 (edited)
Avatar
ですね。
Avatar
omochimetaru 12/4/2018 4:43 AM
default: "nil" はめっちゃいいな
Avatar
Kishikawa Katsumi 12/4/2018 4:48 AM
前にゆってたやつ
Avatar
omochimetaru 12/4/2018 4:48 AM
ですね
Avatar
norio_nomura 12/5/2018 3:35 AM
swift-5.0-branchSequence周りがぶっ壊れてるぽい。
Avatar
norio_nomura 12/6/2018 1:20 AM
Swift 5、@autoclosureで受け取ったクロージャを@autoclosureなパラメータへ渡せなくなってる。 $ docker run --privileged -it --rm norionomura/swift:5020181204a swift Welcome to Swift version 5.0-dev (LLVM 9a8bf9ce12, Clang eba26b8d1c, Swift b74d54a27c). Type :help for assistance. 1> func takeAutoclosure(_ closure: @autoclosure () -> String) { 2. takeAutoclosure(closure) 3. } error: repl.swift:2:21: error: function produces expected type 'String'; did you mean to call it with '()'? takeAutoclosure(closure) ^~~~~~~ ()
Avatar
これってクロージャを実行するクロージャに展開されるんでしょうか
Avatar
norio_nomura 12/6/2018 1:23 AM
エラーメッセージに従って直すと、そうなりますよね。
1:24 AM
4.2まではクロージャのまま渡せてた。 (edited)
Avatar
ですよね、地味に辛い
Avatar
omochimetaru 12/6/2018 1:26 AM
無意味なオーバーヘッドが強制されてしまうのか
Avatar
norio_nomura 12/6/2018 1:29 AM
報告しておいた。 https://bugs.swift.org/browse/SR-9420 (edited)
Avatar
https://github.com/apple/swift/pull/20152 でなされた意図的なものなのですね。-swift-version 4.2 での互換性は保たれているはず。
These changes aim to: Move @autoclosure flag from function type to parameter declaration Serialize @autoclosure as part of the parameter declaration Convert it from being a type attribute to be d...
Avatar
norio_nomura 12/6/2018 1:45 AM
ありがとうございます。
1:50 AM
Swift 5.0スナップショットでYamsのCIを毎日走らせようと試してたのだけど、自前のコレクションでSequence.compactMap()を使うと無限ループになってしまうので、テストにタイムアウトの仕組みとか入れないと怖くてCI設定できない…
Avatar
Kishikawa Katsumi 12/6/2018 1:52 AM
だいたいのCIサービスは時間でAbortするんじゃないです?
Avatar
norio_nomura 12/6/2018 1:54 AM
そうなんだけど、毎日CI自身のタイムアウトまで実行してしまうと、Plan Usageが60倍くらい増えるんじゃ無いかな…
1:56 AM
Array.append(contentsOf:)Sequence.forEach(_:)でクラッシュ、Sequence.sort(_:)Sequence.compactMap(_:)で無限ループが起きるみたいで、Yamsのテストだと再現するけど、PlaygroundやREPLで再現しない 😥 (edited)
2:02 AM
ちなみに無限ループを放置するとメモリを大量に消費して、macOSがクラッシュする。
Avatar
omochimetaru 12/6/2018 2:03 AM
謎なバグですね。
Avatar
norio_nomura 12/6/2018 2:05 AM
ステップ実行で確認すると、IteratorProtocol.next()nilを返してもループを抜けないみたい。
Avatar
Kishikawa Katsumi 12/6/2018 2:12 AM
費用がかさむっていう話なんですね。。。😞
Avatar
norio_nomura 12/6/2018 6:42 AM
stdlibのソースを読むとSequence準拠の型で public __consuming func makeIterator() -> Iterator { の様になってるけど、我々がSequence準拠の型を書く時にも__consumingをつける必要があるのかな?
Avatar
omochimetaru 12/6/2018 6:43 AM
ownershipに関してはオーバーライド関係があって
6:43 AM
例えばmoveを要求する場面で実際にはcopyしても問題ないみたいな
6:44 AM
consumingはselfの所有権の破棄だから、Sequenceの1回だけ読める性質を表していて
6:44 AM
てことは、準拠するときにconsumingをつけなくっても、
6:44 AM
問題はなさそう?
6:45 AM
インターフェースとしては保守的に1回だけ読んでselfがアクセス不能になるけど、実際の型のふるまいとしてはselfが生きてる、で正しい気がします
Avatar
norio_nomura 12/6/2018 7:35 AM
うーん、プロトコル定義に__consumingが付いていて、準拠する型の定義に付いている/付いていないでは、一応生成されるコードが違うぽい? https://github.com/apple/swift/blob/master/test/SILGen/value_ownership.swift
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
7:35 AM
OwnershipManifestを読んでも、よくわからない。
Avatar
omochimetaru 12/6/2018 7:35 AM
それはそうだと思います、付いてないfuncで準拠する場合、consuming版としてthunkが必要
Avatar
norio_nomura 12/6/2018 7:52 AM
Hello Swift Evolution, Over the course of summer of 2017, I was tasked with exploring the implementation of ownership annotations for the Swift language. The goal at the time was to release this proposal at the end of my time and un-underscore the attributes after we had co...
Avatar
omochimetaru 12/6/2018 7:52 AM
これですね
7:52 AM
func に対して付けられるのが3つあって
7:56 AM
selfに対する意味が代わる nonmutating : selfをshared渡しする mutating : selfをinout渡しする consuming: selfの所有権を譲る ( selfはdeinitされたような扱いでそこで使えなくなる )
7:58 AM
引数にはshared / inout / ownedがあって、これまでの無指定はowned相当らしいけど、 引数のownedとselfのconsumingの間に対応があるのか無いのかよくわからないです
Avatar
norio_nomura 12/6/2018 8:16 AM
selfはdeinitされたような扱いでそこで使えなくなる って、将来のmoveonlyな型についてのOwnershipManifest内の説明ですよね。 今使われてる、moveonlyではない型についてはどんな効果があるのだろう?
Avatar
omochimetaru 12/6/2018 8:17 AM
moveは普通の型でもできるから普通の型でもそうだと思ってました。 moveonlyっていうのは、can not copyというのが言いたい事であって、 イメージとしては、今までの型がすべてCopyable、新しくCopyableでない型を追加したいという話
8:19 AM
【可能性1】 今までの型: copyとmoveができる moveonly型 copyができなくて、常にmoveしないといけない型 consming: メソッドレシーバのselfの所有権をメソッド内部にmoveする (edited)
8:20 AM
でも逆の考え方もできそうですね。 【可能性2】 moveonlyではない通常の型の場合、consumingメソッドの呼出しに対して、 selfのコピーを作成してそのコピーをメソッド内部にmoveする。 そうするともともとのレシーバは生き続ける。 (edited)
Avatar
norio_nomura 12/6/2018 8:25 AM
__consumingメソッド内でのselfは常にコピーされたモノになるという事?
Avatar
omochimetaru 12/6/2018 8:27 AM
可能性2の場合そうなりますね。
Avatar
norio_nomura 12/6/2018 8:37 AM
なるほど。
Avatar
omochimetaru 12/6/2018 8:37 AM
僕もドキュメントからそう考えただけで、確認はまだです。現状のアンスコ版とかで試せそうですね。
Avatar
norio_nomura 12/6/2018 8:44 AM
xcrun --toolchain org.swift.5020181204a swiftc -emit-sil swift/test/SILGen/value_ownership.swift の出力を見た感じ、教えて頂いた説明で合ってそうです。 (edited)
Avatar
omochimetaru 12/6/2018 8:44 AM
可能性2?1?
Avatar
norio_nomura 12/6/2018 8:45 AM
あ、呼び出し前にコピーが発生しているかどうかは、これではわからないか。
Avatar
2っぽい動き。 public struct S<T> { var x: T public __consuming func foo() {} } public func testing<T>(c: S<T>) { c.foo() }__consuming 有り無しで
8:46 AM
あり // S.foo() sil @$s4test1SV3fooyyF : $@convention(method) <T> (@in S<T>) -> () { // %0 // users: %2, %1 bb0(%0 : $*S<T>): debug_value_addr %0 : $*S<T>, let, name "self", argno 1 // id: %1 destroy_addr %0 : $*S<T> // id: %2 %3 = tuple () // user: %4 return %3 : $() // id: %4 } // end sil function '$s4test1SV3fooyyF' // testing<A>(c:) sil @$s4test7testing1cyAA1SVyxG_tlF : $@convention(thin) <T> (@in_guaranteed S<T>) -> () { // %0 // users: %3, %1 bb0(%0 : $*S<T>): debug_value_addr %0 : $*S<T>, let, name "c", argno 1 // id: %1 %2 = alloc_stack $S<T> // users: %6, %5, %3 copy_addr %0 to [initialization] %2 : $*S<T> // id: %3 // function_ref S.foo() %4 = function_ref @$s4test1SV3fooyyF : $@convention(method) <τ_0_0> (@in S<τ_0_0>) -> () // user: %5 %5 = apply %4<T>(%2) : $@convention(method) <τ_0_0> (@in S<τ_0_0>) -> () dealloc_stack %2 : $*S<T> // id: %6 %7 = tuple () // user: %8 return %7 : $() // id: %8 } // end sil function '$s4test7testing1cyAA1SVyxG_tlF'
8:47 AM
呼び出し側でコピーして、callee 側で破棄している。
8:47 AM
なし // S.foo() sil @$s4test1SV3fooyyF : $@convention(method) <T> (@in_guaranteed S<T>) -> () { // %0 // user: %1 bb0(%0 : $*S<T>): debug_value_addr %0 : $*S<T>, let, name "self", argno 1 // id: %1 %2 = tuple () // user: %3 return %2 : $() // id: %3 } // end sil function '$s4test1SV3fooyyF' // testing<A>(c:) sil @$s4test7testing1cyAA1SVyxG_tlF : $@convention(thin) <T> (@in_guaranteed S<T>) -> () { // %0 // users: %3, %1 bb0(%0 : $*S<T>): debug_value_addr %0 : $*S<T>, let, name "c", argno 1 // id: %1 // function_ref S.foo() %2 = function_ref @$s4test1SV3fooyyF : $@convention(method) <τ_0_0> (@in_guaranteed S<τ_0_0>) -> () // user: %3 %3 = apply %2<T>(%0) : $@convention(method) <τ_0_0> (@in_guaranteed S<τ_0_0>) -> () %4 = tuple () // user: %5 return %4 : $() // id: %5 } // end sil function '$s4test7testing1cyAA1SVyxG_tlF' オーナーシップ系の動きは一切ない。
Avatar
omochimetaru 12/6/2018 8:48 AM
おお!ほんとだ!
8:49 AM
なるほど、ジェネリック型にすることで最適化を抑制してcopy_addrとdestory_addrが出てきてわかりやすい (edited)
Avatar
public protocol P { func foo() } public struct S<T>: P { var x: T public __consuming func foo() {} } public func testing<T: P>(c: T) { c.foo() } これのときに、
8:57 AM
ああ、sil が張れない。
8:58 AM
GitHub Gist: instantly share code, notes, and snippets.
8:59 AM
S.foo() 内で destroy しているけど、呼び出し側でコピーが無い。これ大丈夫なのかな?
Avatar
norio_nomura 12/6/2018 9:01 AM
これ、destroy_addrが生成されるのとrelease_valueが生成されるのは、どんな違いがあるのですか? https://github.com/apple/swift/blob/master/test/SILGen/value_ownership.swift だと後者が生成される。
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 12/6/2018 9:01 AM
これ大丈夫
引数を破棄してる?
Avatar
norio_nomura 12/6/2018 9:02 AM
あ、これってmakeIterator()で壊れる原因なのでは… (edited)
Avatar
makeIterator() で壊れる原因
それを疑っています。 self が破棄されている可能性。
9:05 AM
non-__consuming な protocol 要求に __consuming で準拠するテストケースはあるのかな?
Avatar
public protocol P { func foo() } public struct S<T>: P { var x: T public __consuming func foo() {} } public func testing<U: P>(_ obj: U) { for _ in 0..<10 { obj.foo() } } class CC { } let obj = S(x: CC()) testing(obj) とりあえずクラッシュするテストケースできました
Avatar
omochimetaru 12/6/2018 9:15 AM
複数回呼べてオーバーデストロイになるんですね
Avatar
norio_nomura 12/6/2018 9:15 AM
makeIterator()の場合、protocolが__consumingですね。
Avatar
ああ、逆なのですね。だとすると、メモリリーク系か?
Avatar
norio_nomura 12/6/2018 9:17 AM
GitHub Gist: instantly share code, notes, and snippets.
9:18 AM
protocol witness for P.foo() in conformance S<A>destroy_addrを生成するのに、呼び出し時にコピーされませんね。
Avatar
これだと呼び出し側が P になってないです。
Avatar
omochimetaru 12/6/2018 9:19 AM
りんたろーさんのやつは、protocolとしては non-consmingだから、呼出し時にコピーが無いけど
Avatar
norio_nomura 12/6/2018 9:19 AM
ぬ。
Avatar
omochimetaru 12/6/2018 9:19 AM
実際に呼ばれてるのはconsumingだから内部にデストロイがあって壊れる?
9:19 AM
本当はコピーしてからメソッドを呼び出すようなthunkを生成して、そのthunkによってprotocol witness tableを埋めないといけないけど
9:19 AM
まだ作ってないとかかな。
Avatar
norio_nomura 12/6/2018 9:21 AM
あ、ちょっと離席するけど、YamsでmakeIterator()__consumingにしても、やっぱりfor inは無限ループになった事は確認ずみ。ちょっと状況が違うのかも。
Avatar
norio_nomura 12/6/2018 9:50 AM
そういえば、Collectionプロトコルにはoverride func makeIterator() -> Iteratorとか含まれるのだけど、これって関係するのかな。
Avatar
Yamsのテストがクラッシュしたり無限ループになったりしてたの、swift-5.0-DEVELOPMENT-SNAPSHOT-2018-12-08-aで直ってた。
Avatar
お。
Avatar
正確には 2018-12-06 -> 2018-12-07 で直ったぽい。
Avatar
So we discovered last night that variadic enum cases work in Swift 4.2 when asserts are off: enum E { case numbers(_: Int...) } E.numbers(1, 2, 3)
11:33 PM
@swift-4.1.3 @swift-4.2.4 -frontend -repl enum E { case numbers(_: Int...) } E.numbers(1, 2, 3)
Avatar
stderr:<REPL Input>:1:29: error: cannot create a variadic tuple enum E { case numbers(_: Int...) } ^ <REPL Input>:1:1: error: use of unresolved identifier 'E' E.numbers(1, 2, 3) ^
Avatar
// r0 : E = REPL.E.numbers([1, 2, 3])
Avatar
それウケる
Avatar
Improving OS Log using Custom String Interpolation and Compile-time Interpretation Hi all, I, along with @Ben_Cohen, @moiseev and @Devin_Coughlin, have been working on improving Swift APIs for Apple's unified logging system, based on some recent exciting developments to the ...
Avatar
5:36 AM
これ欲しかった奴っぽい
Avatar
コンパイル時書式構築自体は良いと思うんだけど、なんでOSLogの改修として出てくるんだろ Foundation.String(format:) 相当の標準が先に欲しいと思った
6:55 AM
書き込んどくか
Avatar
Kishikawa Katsumi 12/16/2018 8:35 PM
@swiftbot versions
Avatar
development_2018-12-15-a swift-5.0-branch_2018-12-14-a 4.2.1 4.1.3 4.1.2 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
Kishikawa Katsumi 12/16/2018 8:36 PM
^ Swift 5のスナップショットを使えるようにしました。
8:37 PM
https://swift-playground.kishikawakatsumi.com WebのPlaygroundもSwift 5が選べるように。他に良いサンプルがあったら教えてください。 StringInterpolationのサンプルはうまく動きませんでした 😢
Avatar
Kishikawa Katsumi 12/16/2018 9:02 PM
@swiftbot --version latest extension String.StringInterpolation { mutating func appendInterpolation<T>(_ val: T?, default defaultValue: String) { if let val = val { appendInterpolation(val) } else { defaultValue.write(to: &self) } } } let value: Int? = nil print("The value is: \(value, default: "<nil>")")
🛠 1
Avatar
Author icon
kishikawakatsumi
extension String.StringInterpolation { mutating func appendInterpolation<T>(_ val: T?, default defaultValue: String) { if let val = val { appendInterpolation(val) } else { defaultValue.write(to: &self) } } } let value: Int? = nil print("The value is: \(value, default: "<nil>")")
Version:
swift-DEVELOPMENT-SNAPSHOT-2018-12-15-a
Output:
Error:
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)[0x7f5500154390] [0x7f55005834e8] [0x7f5500583343] [0x7f550058313a] /usr/bin/swift[0xcec7de] /usr/bin/swift[0xcf09f2] /usr/bin/swift[0x515eff] /usr/bin/swift[0x4eae3e] /usr/bin/swift[0x4e6712] /usr/bin/swift[0x48db1e] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f54fe87e830] /usr/bin/swift[0x48b959] Segmentation fault (core dumped)
Avatar
Kishikawa Katsumi 12/16/2018 9:04 PM
TAny にすると動く
9:04 PM
@swiftbot --version latest extension String.StringInterpolation { mutating func appendInterpolation(_ val: Any?, default defaultValue: String) { if let val = val { appendInterpolation(val) } else { defaultValue.write(to: &self) } } } let value: Int? = nil print("The value is: \(value, default: "<nil>")")
🛠 1
Avatar
Author icon
kishikawakatsumi
extension String.StringInterpolation { mutating func appendInterpolation(_ val: Any?, default defaultValue: String) { if let val = val { appendInterpolation(val) } else { defaultValue.write(to: &self) } } } let value: Int? = nil print("The value is: \(value, default: "<nil>")")
Version:
swift-DEVELOPMENT-SNAPSHOT-2018-12-15-a
Output:
The value is: <nil>
Error:
Avatar
Kishikawa Katsumi 12/16/2018 9:05 PM
nil を渡さなければ T でも動く
9:05 PM
@swiftbot --version latest extension String.StringInterpolation { mutating func appendInterpolation<T>(_ val: T?, default defaultValue: String) { if let val = val { appendInterpolation(val) } else { defaultValue.write(to: &self) } } } let value: Int? = 99 print("The value is: \(value, default: "<nil>")")
🛠 1
Avatar
Author icon
kishikawakatsumi
extension String.StringInterpolation { mutating func appendInterpolation<T>(_ val: T?, default defaultValue: String) { if let val = val { appendInterpolation(val) } else { defaultValue.write(to: &self) } } } let value: Int? = 99 print("The value is: \(value, default: "<nil>")")
Version:
swift-DEVELOPMENT-SNAPSHOT-2018-12-15-a
Output:
The value is: 99
Error:
Avatar
Kishikawa Katsumi 12/16/2018 9:16 PM
Raw Stringはダブルクオートだけ、は無理かな?
9:16 PM
@swiftbot --version latest import Foundation print(#"""#) print(#""""#)
🛠 1
Avatar
Author icon
kishikawakatsumi
import Foundation print(#"""#) print(#""""#)
Version:
swift-DEVELOPMENT-SNAPSHOT-2018-12-15-a
Output:
Error:
/usercode/main.swift:2:11: error: multi-line string literal content must begin on a new line print(#"""#) ^ /usercode/main.swift:3:9: error: multi-line string literal closing delimiter must begin on a new line print(#""""#) ^
Avatar
バグに思える。>ダブルクオートだけ (edited)
Avatar
Kishikawa Katsumi 12/17/2018 12:17 AM
厳密には2連続のダブルクォートで始まる文字列が複数行リテラルの開始と解釈されてしまう、のかな。
Avatar
Kishikawa Katsumi 12/17/2018 12:25 AM
自分で直せそうな気がしないでもない。
Avatar
@swift-5.0.3 @swift-main extension String.StringInterpolation { mutating func appendInterpolation<T>(_ val: T?, default defaultValue: String) { if let val = val { appendInterpolation(val) } else { defaultValue.write(to: &self) } } } let value: Int? = nil print("The value is: \(value, default: "<nil>")")
Avatar
exit status: 11 with stderr: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 0x000000000460a444 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x460a444) #1 0x0000000004608210 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4608210) #2 0x000000000460a5f2 SignalHandler(int) (/usr/bin/swift+0x460a5f2) #3 0x00007f5f29f4b390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f5f2a37a4e8 #5 0x00007f5f2a37a343 #6 0x00007f5f2a37a13a #7 0x0000000000ceca9e llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) (/usr/bin/swift+0xceca9e) #8 0x0000000000cf0cb2 llv
Avatar
swiftNightly BOT 12/17/2018 6:15 AM
exit status: 11 with stderr: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) (/usr/bin/swift+0x460a372) #3 0x00007f05541f1390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f05546204e8 #5 0x00007f0554620343 #6 0x00007f055462013a #7 0x0000000000cec7de llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) (/usr/bin/swift+0xcec7de) #8 0x0000000000cf09f2 llv
Avatar
Linux のバグなのかなー 手元のmacだと動く。
Avatar
https://github.com/apple/swift/pull/21378 お知らせ:import したモジュールに標準ライブラリと同名のものがあった場合、常に明示的に import したほうが優先されるようになります。
Tweak the shadowing rules in two ways: For unqualified type lookup, apply shadowing rules. Without this, we would always get an ambiguity if there were two types with the same name, so this should...
11:46 PM
これによって Swift.Result より他の Result が優先されるのでソース互換が保たれます。
☺ 1
🙏 1
♥ 4
11:48 PM
EncodableDecodable 導入されたときにこのルールになってればいろいろ楽だったのになー。。。
Avatar
Kishikawa Katsumi 12/18/2018 1:33 AM
これはわかりやすいルールでいいですね。
Avatar
そうか、ユーザ型と同名のstd型、いまさらあんまり無さそうだけど、Result は盛大にかぶりますもんね
Avatar
Result.Resultが出来ないからというのも
Avatar
そっちはそっちで言語に改修が必要そう。
1:44 AM
@modulename Result.Result ResultモジュールのResult型 Result.Result Result型のinner型のResult型 みたいな
Avatar
SR-5719: In Swift 5 mode, @autoclosure parameters can no longer be forwarded to @autoclosure arguments in another function call. Instead, you must explicitly call the function value with (); the call itself is wrapped inside an implicit closure, guaranteeing the same behavior as in Swift 4 mode. Example: func foo(_ fn: @autoclosure () -> Int) {} func bar(_ fn: @autoclosure () -> Int) { foo(fn) // Incorrect, `fn` can't be forwarded and has to be called foo(fn()) // Ok }
2:02 AM
The Swift Programming Language. Contribute to slavapestov/swift development by creating an account on GitHub.
2:02 AM
@norio_nomura が前話してたautoclosureの仕様変更、Swift5向けの変更だってハッキリ書かれてた (edited)
👍 1
Avatar
same behavior って書かれてるけど、クロージャのラップ回数が一個増えてパフォーマンスが低下してるような気がする
Avatar
そんな話を前にここでしてた (edited)
4:12 AM
これってasyncやらの絡みでそうなるんですかね
4:12 AM
リンクされてるSRを見るとそうでもない
4:13 AM
func autoclosureFoo(_ c: @autoclosure () -> Int) { print(c()) } func autoclosureBar(_ c: @autoclosure () -> Int) { autoclosureFoo(c) // <-- This one here autoclosureFoo(c()) } func baz(_ c: () -> Int) { autoclosureFoo(c) // does not work as expected } autoclosureBar(42)
4:14 AM
これに一貫性が無いって話で
Avatar
なるほど
Avatar
These changes aim to: Move @autoclosure flag from function type to parameter declaration Serialize @autoclosure as part of the parameter declaration Convert it from being a type attribute to be d...
4:17 AM
これで対応されてるんだけど、ここの文言を見る限り
4:17 AM
@autoclosure ってもともとの仕様だと型なんだよね
4:17 AM
autoclosureにautoclosureはクロージャ型のまま引き渡せるのに対して、 autoclosureに普通のクロージャは渡せないから、
4:17 AM
型システム的に取り扱いが区別されてる
4:18 AM
で、これがパラメータ属性に変更されて、型としての扱いは普通のクロージャになった
4:19 AM
から、今後はフォワードさせたい場合は () をつけましょうね、ということになる
Avatar
@rintaro Linux のバグなのかなー 手元のmacだと動く。 これ、LinuxでREPLの標準入力へそのソースコードを渡した時だけクラッシュする様です。
9:44 AM
LinuxのインタラクティブなREPLで入力してもクラッシュしません。
Avatar
あいや、正確にはLinuxのREPLへソースコードをファイル(標準入力含む)で渡した時にクラッシュ、だ。
10:15 AM
swiftcでexecutableを生成して実行してもクラッシュしない。 (edited)
Avatar
初めて質問させてもらいます! ライブラリのTabPageViewControllerを使っているのでが、 このライブラリを使ってツイッターのプロフィール画面のような上にプロフィール部分があり、下にスクロールできるViewがあるもの作ることできますでしょうか? どうすればTab部分の上にViewを配置できるのかが分からず悩んでいます。 https://github.com/EndouMari/TabPageViewController
Paging view controller and scroll tab view. Contribute to EndouMari/TabPageViewController development by creating an account on GitHub.
2:47 PM
またできればツイッターアプリのような動きでスクロールした際にTab上部のみ隠れるようにできれば嬉しいです。
Avatar
上記解決しました🙇
Avatar
Kishikawa Katsumi 12/22/2018 12:42 PM
Swift AST Explorerを最新のSwiftSyntaxを使うように更新しました。以前は独立したプロジェクトになる前のだいぶ古いものを参照していた(Linuxビルドも公式にはサポートされてなかった)から最新の結果が返るようになったはず! https://swift-ast-explorer.kishikawakatsumi.com/
👀 1
Avatar
Kishikawa Katsumi 12/22/2018 7:45 PM
https://github.com/kishikawakatsumi/swift-magic ファイル種別を判定するライブラリ、libmagic のSwiftラッパーライブラリを作りました。
A Swift wrapper for libmagic. Contribute to kishikawakatsumi/swift-magic development by creating an account on GitHub.
Avatar
SwiftのDictionaryのキーにプロトコル使えますか?もしくはそういう場面に出くわしたときの代替案はありますか? ユースケースとしては、DictionaryLiteralpairs 変数のキーに ExpressionType を入れたいです。試した方法は下記のリンクとほぼ同じです。 ExpressionType を内部で持つ AnyLiteral みたいなstructを定義する以外の方法が思いつかない... https://forums.developer.apple.com/message/9175#9175 ソースコードの例です。インタープリタを実装していて、Dictionaryリテラルを追加しようとしています。 enum TokenKind: Int, Hashable { case integer case string case dictionary } protocol ExpressionType { var token: TokenKind { get } } struct IntegerLiteral { let value: Int64 } extension IntegerLiteral: ExpressionType { var token: TokenKind { return .integer } } struct StringLiteral { let value: String } extension StringLiteral: ExpressionType { var token: TokenKind { return .string } } struct DictionaryLiteral { let pairs: [ExpressionType: ExpressionType] } extension DictionaryLiteral: ExpressionType { var token: TokenKind { return .dictionary } } (edited)
I'm wondering, is it even possible to create a Set in Swift whose members are guaranteed only to share conformance to a Protocol? My initial attempt
Avatar
DictionaryLiteralpairsDictionary<ExpressionType, ExpressionType>ではなくKeyValuePairs<ExpressionType, ExpressionType>にするとか…
Avatar
そうか、KeyValuePairs はHashable準拠してなくても良いのか。まずはその方法で実装してみます、ありがとうございます! DictionaryLiteral は名前かぶってるのでリネームしたほうが良いな...
Avatar
この、ExpressionTypeをキーにしたいんですよね、Hashable準拠にして実装はAnyHashableにしておくとかで誤魔化せないでしょうか?
2:21 PM
HasherにObjectIdentifer(Self.self)を食べさせれば型ごとにもユニークになるはず
Avatar
そう、AnyHashableは最初にパッとやってみた。どっちのほうが良いか実装して今比べてます。
Avatar
普通は書いた順に評価されることを保証すると思うので、 { "a": foo(), "b": bar() } みたいなときに foo(), bar() の順で実行するためには Dictionary ではなく、 KeyValuePairsArray<(key: ExpressionType, value: ExpressionType)> のほうが良いと思います。 (edited)
Avatar
確かにその方が良いですね。修正してみます!
Avatar
Swift 5のString.UTF8View.withContiguousStorageIfAvailable(_:)、macOSだとStringの作り方によって使えたり使えなかったりする。
12:05 PM
$ xcrun --toolchain org.swift.5020181228a swift swift_oss_helper command enabled. Welcome to Apple Swift version 5.0-dev (LLVM c351ac7354, Clang aadec4ff83, Swift 5cfc2e7ba9). Type :help for assistance. 1> import Foundation 2. let url = URL(fileURLWithPath: "/etc/passwd") 3. let a = String(data: try Data(contentsOf: url), encoding: .utf8)?.utf8.withContiguousStorageIfAvailable { $0.count } 4. let b = try String(contentsOf: url, encoding: .utf8).utf8.withContiguousStorageIfAvailable { $0.count } url: URL = "file:///etc/passwd" a: Int? = 6804 b: Int? = nil 5> (edited)
Avatar
@swift-4.2.4 import Foundation let formatter = DateFormatter() formatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "YYYY-MM-dd", options: 0, locale: Locale(identifier: "ja_JP")) print(formatter.string(from: Date()))
Avatar
2019/12/31
Avatar
もうすぐ2020年ですね・・・・・? どういう事なんだろうこれ (edited)
8:33 PM
タイムゾーン周りで指定ミスっているなら9時間前後ズレるならわかるんだけど、1年近くズレる
8:33 PM
ちなみに29日だと大丈夫だった。時間周りで知らない仕様があるのか、バグなのかどっちなんだろ
Avatar
@swift-4.2.4 import Foundation let formatter = DateFormatter() formatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "yyyy-MM-dd", options: 0, locale: Locale(identifier: "ja_JP")) print(formatter.string(from: Date()))
Avatar
2018/12/31
Avatar
大文字のYと小文字のyは意味が違ったと思う
Avatar
ある年における「最初の木曜日を含む週が、その年の第1週である」というルールで年(西暦)を出力。
8:34 PM
知らなかった・・・
8:34 PM
@omochimetaru ありがとうございます…!
Avatar
つまりどういうことだってばよ
Avatar
Kishikawa Katsumi 12/30/2018 8:36 PM
2019年の最初の木曜日は1/3なので、その週である12/31は2019年となる、ということのはず。
8:36 PM
12/31は2019年の第1週と扱われる。
Avatar
ああなるほど!日本語の意味がわかりましたw
Avatar
2019年はYYYYだと12/31(30?)から始まって12/29で終わるみたいな感じなんですね
Avatar
なんかこれ踏んだ事があって、年末の数日間だけバグが出た事があって、それで覚えていた。
Avatar
Kishikawa Katsumi 12/30/2018 8:40 PM
使ったことないけど、週番号を表示するカレンダーを作る場合には有用なんだろうか。
Avatar
その日付がどの週に所属するか、を求めるときに使えるんですかね。
Avatar
The end of the year is rolling around and it’s time to remind everyone about that yyyy works the way you think it does and YYYY does not. Here’s a quick example to start: Just because y…
Avatar
omochimetaru 1/7/2019 4:32 AM
Pitch: Introducing fold to reduce a sequence onto its own elements and eliminate common errors Work in progress is at this gist. Please refer to the gist for the latest updates as this post and thread may be out of date. Draft follows. Constructive feedback is greatly appre...
4:32 AM
Erica SadunさんのPitchで、クロージャしか取らないreduceの提案。
4:32 AM
足し算なら0, 掛け算なら1, みたいな初期値の指定が無いやつ。 配列が空の場合は nil になる。 (edited)
4:34 AM
既存のreduceにはinout版のオーバーロードがあるけど、そっちはreduce(into:) { ... } でラベルがあったので良かったけど、 これにも同じものを用意しようとするとダメそうなのが気になる。
4:35 AM
この提案自体ではそれに触れてないけど、reduce(into:)の必要性の議論はそのままinitialValue無しのreduceにも適用できるはず
Avatar
compactMapValuesが壊れるw
Avatar
omochimetaru 1/7/2019 6:33 AM
既存のinitialValue付きを削除するわけじゃないから壊れることはない?
Avatar
これは結構無理がある気がする、処理の初期値として何が正しいかをコンパイラが理解するのは至難じゃないの
Avatar
omochimetaru 1/7/2019 7:17 AM
初期値は array[0] と array[1] だよ。
Avatar
なるほど?
7:18 AM
そういうことか
Avatar
omochimetaru 1/7/2019 7:18 AM
初期値が array[0] で、最初に呼ばれるクロージャが array[0] と array[1] のペア。
7:18 AM
要素が1個ならクロージャを呼ばずにarray[0]を返す 要素が0個ならnil
7:18 AM
reduce<R>のRの型がArray.Elementに固定されている。
Avatar
reduceはRの型が変動するイメージが結構強い、固定されるなら名前変えた方がいいのではみたいな
7:19 AM
議論すでにありそう、読んでみるか
Avatar
omochimetaru 1/7/2019 7:19 AM
[1, 2, 3] の合計を求めたいときにわざわざ 0 + 1 + 2+ 3 って式を計算させるのはナンセンスだし、欲しい。
Avatar
名前はfoldの方が良さそう
7:20 AM
すでに書かれてるな
Avatar
Kishikawa Katsumi 1/8/2019 5:27 AM
InputStream(Swift)/NSInputStream class has wasteful complicated functional. Its not useful and hard to understand.
^ なるほど。
Avatar
omochimetaru 1/8/2019 5:28 AM
エラーハンドリングもstreamErrorプロパティを逐次確認するという謎仕様なのでSwift的じゃないですし。 そのへんは好みと言われたら終わりですが、ただ、シークできないという点は機能として致命的に思います。
5:30 AM
(1)は、stdlibでは今の所ファイルシステムの面倒を見てるやつらが無いし、Foundationは歴史の塊だから、 そのへんは今の所スコープじゃないと言われそうですが、 (2)と(3)はもうちょっと整備されてほしいなあ。
Avatar
norio_nomura 1/10/2019 1:49 AM
antitypical/Resultを使ってるコードを、最小限の変更でSwift.Resultに対応させられるPRを書いた。 https://github.com/antitypical/Result/pull/280
Avatar
omochimetaru 1/10/2019 1:50 AM
#if swift(>=4.2) #if compiler(>=5) なるほど!w
1:50 AM
compilerなんてありましたっけ。
Avatar
norio_nomura 1/10/2019 1:50 AM
とりあえずCommandantとかは、変更なしでantitypical/ResultをバージョンアップするだけでSwift.Resultを使う様になる事を確認。 (edited)
1:51 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 1/10/2019 1:51 AM
おお
1:52 AM
コンパイラのバージョンがswiftで、コンパイラが動作してるswift互換モードのバージョンがcompilerなのか。 (edited)
1:52 AM
たしかにそれがないとどうしようもないな。
Avatar
norio_nomura 1/10/2019 1:53 AM
#if swift(…)はlanguage versionで、コンパイラに渡す-swift-versionの影響を受ける。
Avatar
omochimetaru 1/10/2019 1:53 AM
あ、逆か
Avatar
norio_nomura 1/10/2019 1:53 AM
#if compiler(…)-swift-versionの影響を受けません。
Avatar
norio_nomura 1/10/2019 3:30 AM
Semantic Versioningの観点からSwift 5オンリーにした方が良いと言われたのだけど、そうなのだろうか。 https://github.com/antitypical/Result/pull/280#discussion_r246621449
Avatar
norio_nomura 1/10/2019 1:55 PM
結局そのままマージさせてもらった。
Avatar
https://forums.swift.org/t/why-doesnt-this-do-what-i-thought-it-would/19407 @swiftbot struct HaveResult { var resultCode = 0 func returnResultCode(_ value: Int) -> Int { return resultCode } } func testA() { var r = HaveResult() print(r.returnResultCode(changeResult(r: &r))) } func testA_variant() { var r = HaveResult() let r2 = r print(r2.returnResultCode(changeResult(r: &r))) } func testB() { var r = HaveResult() let x = changeResult(r: &r) print(r.returnResultCode(x)) } func changeResult(r: inout HaveResult) -> Int { r.resultCode = 1 return 0 } testA() testA_variant() testB()
struct OpentimeErrorThrower { var resultCode = 0 var details = "" func returnOrThrow(_ value: T) throws -> T { if resultCode == 0 { return value } throw Error("oops") } } func doesntWorkCorrectly() throws -> Int { var et = ...
🛠 1
Avatar
swiftbot BOT 1/11/2019 2:41 AM
Author icon
t.ae
struct HaveResult { var resultCode = 0 func returnResultCode(_ value: Int) -> Int { return resultCode } } func testA() { var r = HaveResult() print(r.returnResultCode(changeResult(r: &r))) } func testA_variant() { var r = HaveResult() let r2 = r print(r2.returnResultCode(changeResult(r: &r))) } func testB() { var r = HaveResult() let x = changeResult(r: &r) print(r.returnResultCode(x)) } func changeResult(r: inout HaveResult) -> Int { r.resultCode = 1 return 0 } testA() testA_variant() testB()
Version:
swift-4.2.1-RELEASE
Output:
0 0 1
Error:
Avatar
これってtest_AはtestA_variantのような動作になってるってことでいいんでしょうか? (edited)
Avatar
omochimetaru 1/11/2019 2:43 AM
パット見inoutの書き戻しと例外での脱出のタイミングの話? (edited)
Avatar
いやCoWがわかりにくいところで働いてるんじゃないかって思っています
Avatar
omochimetaru 1/11/2019 2:44 AM
ちゃんと読んでくる
Avatar
元のコードがわかりにくかった&そのままじゃ実行できなかったので↑のコードは多少シンプルに変えています。 (edited)
Avatar
omochimetaru 1/11/2019 2:47 AM
例外は関係ないのか。
Avatar
r.returnResultCodeのrがCoWで元の値のままのこっていてtestA_variantのようになってるんじゃないかと思っています。
Avatar
omochimetaru 1/11/2019 2:47 AM
まず、Copy on writeは関係ないよ
2:47 AM
Copy on writeはstructにはついてない
2:47 AM
ArrayやDictionaryなどで明示的なコードとして書かれてるだけ
Avatar
Copy on writeという語の僕の頭の中の定義が間違ってそうですね……
Avatar
omochimetaru 1/11/2019 2:49 AM
Copy on writeについてはこれを読むとわかる https://qiita.com/omochimetaru/items/f32d81eaa4e9750293cd
Swift の Array や Dictionary は Copy on Write になっていてとても使いやすいです。この記事では、そのような Copy on Write の実装方法を解説します。

CoW の動作

Copy ...
Avatar
単に値型とこんがらがってただけか。
Avatar
omochimetaru 1/11/2019 2:50 AM
単純にレシーバと引数の評価順の問題な気がする
2:51 AM
r.returnResultCode(changeResult(r: &r)) ここで &r への結果の書き戻しって、changeResultのcallの終わった後だと思うけど
2:51 AM
第一引数changeResultの評価と、レシーバrの評価って、レシーバが先なんじゃないかな
Avatar
そうですね。僕もそういう認識でした。
Avatar
omochimetaru 1/11/2019 2:53 AM
define hidden swiftcc void @"$S1a5testAyyF"() #0 { entry: %0 = alloca %T1a10HaveResultV, align 8 %1 = bitcast %T1a10HaveResultV* %0 to %swift.opaque** store %swift.opaque* null, %swift.opaque** %1, align 8 %2 = bitcast %T1a10HaveResultV* %0 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = call swiftcc i64 @"$S1a10HaveResultVACycfC"() %.resultCode = getelementptr inbounds %T1a10HaveResultV, %T1a10HaveResultV* %0, i32 0, i32 0 %.resultCode._value = getelementptr inbounds %TSi, %TSi* %.resultCode, i32 0, i32 0 store i64 %3, i64* %.resultCode._value, align 8 %4 = call swiftcc { %swift.bridge*, i8* } @"$Ss27_allocateUninitializedArrayySayxG_BptBwlFyp_Tg5"(i64 1) %5 = extractvalue { %swift.bridge*, i8* } %4, 0 %6 = extractvalue { %swift.bridge*, i8* } %4, 1 %7 = call %swift.bridge* @swift_bridgeObjectRetain(%swift.bridge* %5) #2 call void @swift_bridgeObjectRelease(%swift.bridge* %5) #2 %8 = bitcast i8* %6 to %Any* %9 = call swiftcc i64 @"$S1a12changeResult1rSiAA04HaveB0Vz_tF"(%T1a10HaveResultV* nocapture dereferenceable(8) %0)
2:53 AM
%10 = call swiftcc i64 @"$S1a10HaveResultV06returnB4CodeyS2iF"(i64 %9, i64 %3) %11 = getelementptr inbounds %Any, %Any* %8, i32 0, i32 1 store %swift.type* @"$SSiN", %swift.type** %11, align 8 %12 = getelementptr inbounds %Any, %Any* %8, i32 0, i32 0 %13 = getelementptr inbounds %Any, %Any* %8, i32 0, i32 0 %14 = bitcast [24 x i8]* %13 to %TSi* %._value = getelementptr inbounds %TSi, %TSi* %14, i32 0, i32 0 store i64 %10, i64* %._value, align 8 %15 = call swiftcc { %swift.bridge*, i64 } @"$Ss5print_9separator10terminatoryypd_S2StFfA0_"() %16 = extractvalue { %swift.bridge*, i64 } %15, 0 %17 = extractvalue { %swift.bridge*, i64 } %15, 1 %18 = call swiftcc { %swift.bridge*, i64 } @"$Ss5print_9separator10terminatoryypd_S2StFfA1_"() %19 = extractvalue { %swift.bridge*, i64 } %18, 0 %20 = extractvalue { %swift.bridge*, i64 } %18, 1 call swiftcc void @"$Ss5print_9separator10terminatoryypd_S2StF"(%swift.bridge* %5, %swift.bridge* %16, i64 %17, %swift.bridge* %19, i64 %20) call void @swift_bridgeObjectRelease(%swift.bridge* %19) #2 call void @swift_bridgeObjectRelease(%swift.bridge* %16) #2 call void @swift_bridgeObjectRelease(%swift.bridge* %5) #2 %21 = bitcast %T1a10HaveResultV* %0 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %21) ret void }
Avatar
真のtestA_variantはこうか。 func testA_variant() { var r = HaveResult() let f = r.returnResultCode print(f(changeResult(r: &r))) }
Avatar
omochimetaru 1/11/2019 2:55 AM
%9 = call swiftcc i64 @"$S1a12changeResult1rSiAA04HaveB0Vz_tF"(%T1a10HaveResultV* nocapture dereferenceable(8) %0) %10 = call swiftcc i64 @"$S1a10HaveResultV06returnB4CodeyS2iF"(i64 %9, i64 %3) (edited)
2:59 AM
なんか若干怪しいな
2:59 AM
%0にメモリ確保して、 initの返り値が%3に入って、 %3から%0 に代入して、 っていう形で初期化しているけど、 %3をそのまま使ってるな。
Avatar
%3 は変更される前の値だから、予想通りじゃないですか?
3:01 AM
第一引数changeResultの評価と、レシーバrの評価って、レシーバが先
Avatar
omochimetaru 1/11/2019 3:01 AM
ここで%3が来る理由がわからなくて。 rの値を%0から読み出す処理じゃなくてよいのかな。
3:02 AM
%3はあくまでinitの返り値であって、rを表してるわけじゃないというか・・・
3:03 AM
挙動は予想通りだけど、このIRになった生成過程がイメージと一致してなかった。
Avatar
HaveResult 全体が i64 に lowered されてるからわかりにくいのかな。
Avatar
omochimetaru 1/11/2019 3:04 AM
それもありますね。
Avatar
HaveResult.returnResultCode(r)(changeResult(r: &r)) と同等っていうのは説得力ある説明だな。 (edited)
Avatar
omochimetaru 1/11/2019 3:07 AM
define hidden swiftcc i64 @"$S1a10HaveResultV06returnB4CodeyS2iF"(i64, i64) #0 { ↑ returnResultCode が returnB4Code にsubstされてる・・・
3:09 AM
これどうなってんだ・・・
Avatar
@rintaro taylorswiftさんが良い説明してくれましたね。 僕も上で話した内容で理解がまとまりました。ありがとうございます。
Avatar
omochimetaru 1/11/2019 3:12 AM
置換 A = Have, B = Result だ
3:13 AM
そういうことか、 10HaveResult のときに HaveResultが辞書入りするんじゃなくて、 Have / Result にワード分割するのか
3:14 AM
クラス名とか CamelCase になりがちだからそうやっとくと便利みたいなやつか・・・
3:14 AM
さっきのやつだけど、
3:15 AM
本来structのメソッドレシーバはポインタ渡しだから
3:15 AM
この挙動は起きないはずで
3:15 AM
サイズが小さい時にレシーバを引数に並べちゃう値型の最適化が
3:15 AM
あったからこの挙動なんじゃないか
Avatar
structのサイズが大きいと挙動が異なる可能性がある?
Avatar
omochimetaru 1/11/2019 3:19 AM
define hidden swiftcc i64 @"$S1a5testASiyF"() #0 { entry: %0 = alloca %T1a10HaveResultV, align 8 %1 = alloca %T1a10HaveResultV, align 8 %2 = bitcast %T1a10HaveResultV* %1 to %swift.opaque** store %swift.opaque* null, %swift.opaque** %2, align 8 %3 = bitcast %T1a10HaveResultV* %0 to i8* call void @llvm.lifetime.start.p0i8(i64 72, i8* %3) %4 = bitcast %T1a10HaveResultV* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 72, i8* %4) call swiftcc void @"$S1a10HaveResultVACycfC"(%T1a10HaveResultV* noalias nocapture sret %0) %5 = bitcast %T1a10HaveResultV* %1 to i8* %6 = bitcast %T1a10HaveResultV* %0 to i8* call void @llvm.memcpy.p0i8.p0i8.i64(i8* %5, i8* %6, i64 72, i32 8, i1 false) %7 = call swiftcc i64 @"$S1a12changeResult1rSiAA04HaveB0Vz_tF"(%T1a10HaveResultV* nocapture dereferenceable(72) %1) %8 = call swiftcc i64 @"$S1a10HaveResultV16returnAesultCodeyS2iF"(i64 %7, %T1a10HaveResultV* noalias nocapture swiftself dereferenceable(72) %0) %9 = bitcast %T1a10HaveResultV* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 72, i8* %9) %10 = bitcast %T1a10HaveResultV* %0 to i8* call void @llvm.lifetime.end.p0i8(i64 72, i8* %10) ret i64 %8 }
3:19 AM
でかくしたらポインタになったけど、そしたらchangeResultにわたすHaveResultとreturnResultCodeを呼び出すHaveResultが別のオブジェクトになって、結果は同じく0だった。
Avatar
@swiftbot struct HaveResult { var resultCode = 0 mutating func returnResultCode(_ value: Int) -> Int { return resultCode } } public func testA() { var r = HaveResult() print(r.returnResultCode(changeResult(r: &r))) } func testA_variant() { var r = HaveResult() var r2 = r print(r2.returnResultCode(changeResult(r: &r))) } func testB() { var r = HaveResult() var x = changeResult(r: &r) print(r.returnResultCode(x)) } func changeResult(r: inout HaveResult) -> Int { r.resultCode = 1 return 0 } testA() testA_variant() testB()
🛠 1
Avatar
swiftbot BOT 1/11/2019 3:20 AM
Author icon
rintaro
struct HaveResult { var resultCode = 0 mutating func returnResultCode(_ value: Int) -> Int { return resultCode } } public func testA() { var r = HaveResult() print(r.returnResultCode(changeResult(r: &r))) } func testA_variant() { var r = HaveResult() var r2 = r print(r2.returnResultCode(changeResult(r: &r))) } func testB() { var r = HaveResult() var x = changeResult(r: &r) print(r.returnResultCode(x)) } func changeResult(r: inout HaveResult) -> Int { r.resultCode = 1 return 0 } testA() testA_variant() testB()
Version:
swift-4.2.1-RELEASE
Output:
1 0 1
Error:
/usercode/main.swift:22:9: warning: variable 'x' was never mutated; consider changing to 'let' constant var x = changeResult(r: &r) ~~~ ^ let
Avatar
mutating にしたら結果が変わると。
Avatar
omochimetaru 1/11/2019 3:20 AM
ウオw
Avatar
これは Exclusivity でエラーになるべきなのかな?
Avatar
omochimetaru 1/11/2019 3:23 AM
&rのアクセスはchangeResultの評価中だけで、changeResultの呼び出し後にメソッド呼び出しだから、セーフな気がする
3:24 AM
どっちかがバグな気がする・・・
Avatar
このスレッドに再現コード張って、意見聞いてみますね。
Avatar
omochimetaru 1/11/2019 3:29 AM
あざます
3:30 AM
struct HaveResult { var resultCode = 0 var padding: (Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64) = (0, 0, 0, 0, 0, 0, 0, 0) func returnAesultCode(_ value: Int) -> Int { return resultCode } } func testA() -> Int { var r = HaveResult() let x = r.returnAesultCode(changeResult(r: &r)) return x } func changeResult(r: inout HaveResult) -> Int { r.resultCode = 1 return 0 } print(testA())
3:30 AM
↑selfがポインタ渡しになるバージョン。でも挙動はもとと同じ。
3:31 AM
(print文があるとIRがしんどいのでちょっと改変してます
Avatar
norio_nomura 1/11/2019 3:42 AM
元の質問に合わせると、let x = r.returnAesultCode(changeResult(r: &r.resultCode))func changeResult(r: inout Int) -> Int { r = 1 return 0 } じゃないかな。
3:43 AM
まあ、結果は同じだけど。
Avatar
ああ、ほんとですね。微妙に間違ってました。
Avatar
protocol P { func hoge(_ a: Int) func hoge(_ a: String) } protocol IntOrString {} extension Int : IntOrString {} extension String : IntOrString {} struct S : P { func hoge<X>(_ a: X) { print("X") } } extension P { func hoge(_ a: Int) { print("default Int") } } let s = S() s.hoge(1) // default Int s.hoge("a") // X
10:08 AM
Generic実装でのプロトコルのオーバーロード一括コンフォームは、
10:08 AM
デフォルト実装よりは優先度が低いのね。
Avatar
そうそう
Avatar
ちょっと変な感じがする。
10:26 AM
通常のコンフォームを満たすときにはPWTのエントリをGeneric版のパラメータを埋めたthunkでフィルしてるはずで、
Avatar
確かに言われてみれば
Avatar
その発想から行くとデフォルト実装があろうがそれよりも優先したい
Avatar
omochimetaru 1/15/2019 3:02 AM
Easily import third-party dependencies in your Swift scripts - mxcl/swift-sh
3:02 AM
#!/usr/bin/swift sh import PromiseKit // @mxcl ~> 6.5 firstly { after(.seconds(2)) }.then { after(.milliseconds(500)) }.done { print("notice: two and a half seconds elapsed") exit(0) } RunLoop.main.run()
3:02 AM
↑こんな感じでSwiftをスクリプト的に使えるやつだそうです、importのところの記法がオシャレだなと思った。
Avatar
リポジトリとframeworkの名前が一致してない場合はどうなるんだろ
5:54 AM
import BumbleButt // https://example.com/bb.git ~> 9 これか
5:54 AM
オシャンだ
Avatar
omochimetaru 1/15/2019 5:56 AM
@xxxxxx/xxx のsugarみたいね import Floobles // mxcl/Flub == master import BumbleButt // https://example.com/bb.git ~> 9 (edited)
Avatar
@swift-4.2.4 @swift-5.0.3 @swift-main protocol P1 { associatedtype X } protocol P2 {} struct Box<T1, T2: P1> { struct X {} } extension Box.X: P2 where T2.X == String {} struct S: P1 { typealias X = String } _ = Box<Int, S>.X.self is P2.Type (edited)
Avatar
stderr:<stdin>:16:24: warning: 'is' test is always true _ = Box<Int, S>.X.self is P2.Type ^ (edited)
Avatar
exit status: 11 with stderr:<stdin>:16:24: warning: 'is' test is always true _ = Box<Int, S>.X.self is P2.Type ^ #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 0x00007fbd9ed2d390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007fbd9aa60210 swift::TargetMetadata<swift::InProcess>::getTypeContextDescriptor() const (/usr/lib/swift/linux/libswiftCore.so+0x3c4210) #5 0x00007fbd9aa798cb searchInConformanceCache(swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*) (/usr/lib/swift/linux/libswiftCore.so+0x3dd8cb) #6 0x00007fbd9aa79343 swift_conformsToProtocolImpl(swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*) (/usr/lib/swift/linux/libswiftCore.so+0x3dd343) #7 0x00007fbd9aa78aa5 swift::_checkGenericRequirements(llvm::ArrayRef<swift::TargetGenericRequirementDescriptor<swift::InProcess> >, std::vector<void const*, std::allocator<void const*> >&, llvm::function_ref<swift::TargetMetadata<swift::InProcess> const* (unsigned int)>, llvm::function_ref<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>) (/usr/lib/swift/linux/libswiftCore.so+0x3dcaa5) #8 0x00007fbd9aa78905 swift::TargetProtocolConformanceDescriptor<swift::InProcess>::getWitnessTable(swift::TargetMetadata<swift::InProcess> const*) const (/usr/lib/swift/linux/libswiftCore.so+0x3dc905) #9 0x00007fbd9aa79a9f swift_conformsToProtocolImpl(swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*)::$_3::operator()(swift::TargetProtocolConformanceDescriptor<swift::InProcess> const&, swift::TargetMetadata<swift::InProcess> const*) const (/usr/lib/swift/linux/libswiftCore.so+0x3dda9f) #10 0x00007fbd9aa79637 swi (edited)
Avatar
swiftNightly BOT 1/15/2019 3:04 PM
stderr:<stdin>:16:24: warning: 'is' test is always true _ = Box<Int, S>.X.self is P2.Type ^ (edited)
Avatar
お、もう直ってるのか〜
3:07 PM
struct Box<T1, T2: P1>: P1 { struct X {} } extension Box.X: P2 where T2.X == String {} ここが肝で struct Box<T1: P1, T2> だとクラッシュしない。
Avatar
omochimetaru 1/17/2019 1:44 AM
@swift-4.2.4 @swift-5.0.3 @swift-main let str = "\u{0336}\u{0344}\u{0357}\u{0343}\u{0314}\u{0351}\u{0340}\u{0300}\u{0340}\u{0360}\u{0314}\u{0357}\u{0315}\u{0301}\u{0344}a" let set = Set([str])
Avatar
no output
Avatar
swiftNightly BOT 1/17/2019 1:44 AM
no output
Avatar
exit status: 4 with stderr:Fatal error: Output buffer was not big enough, this should not happen: file /home/buildnode/jenkins/workspace/oss-swift-4.2-package-linux-ubuntu-16_04/swift/stdlib/public/core/NormalizedCodeUnitIterator.swift, line 177 Current stack trace: 0 libswiftCore.so 0x00007f8205354fa0 _swift_stdlib_reportFatalErrorInFile + 215 1 libswiftCore.so 0x00007f82050ad5c1 <unavailable> + 1504705 2 libswiftCore.so 0x00007f82052ea0c2 <unavailable> + 3850434 3 libswiftCore.so 0x00007f82052ec3b9 <unavailable> + 3859385 4 libswiftCore.so 0x00007f82050acd0a <unavailable> + 1502474 5 libswiftCore.so 0x00007f82052ea008 <unavailable> + 3850248 6 libswiftCore.so 0x00007f82050acd0a <unavailable> + 1502474 7 libswiftCore.so 0x00007f8205246a28 <unavailable> + 3181096 8 libswiftCore.so 0x00007f8205269bfa <unavailable> + 3324922 9 libswiftCore.so 0x00007f8205269c36 <unavailable> + 3324982 10 libswiftCore.so 0x00007f8205269e6b <unavailable> + 3325547 11 libswiftCore.so 0x00007f82051e7870 _StringGuts.hash(into:) + 9 12 libswiftCore.so 0x00007f82051e79c1 <unavailable> + 2791873 13 libswiftCore.so 0x00007f82051d2470 _VariantSetBuffer.nativeInsert(_:forKey:) + 194 14 libswiftCore.so 0x00007f82051c8f70 Set.init<A>(_:) + 796 16 swift 0x0000000001043efe <unavailable> + 12861182 17 swift 0x0000000001048022 <unavailable> + 12877858 18 swift 0x00000000004f8b42 <unavailable> + 1018690 19 swift 0x00000000004df0bb <unavailable> + 913595 20 swift 0x00000000004da3f0 <unavailable> + 893936 21 swift
Avatar
omochimetaru 1/17/2019 1:44 AM
For those who’re interested in what Swift language bug is, which is not fixed yet and still in wild as of current released version of Swift, and will not be fixed until 5.0 release. https://t.co/9BegKKLxy6
Avatar
花芽尋かすみ 1/18/2019 3:02 AM
こないだ当たった問題なんですけど、これわかる方いらっしゃいますか? extension String { init(decimalStyle int: Int) { let formatter = NumberFormatter() formatter.numberStyle = .decimal self = formatter.string(from: int as NSNumber)! } } let ids = [89902,100238,123289] //ids.map(String.init).joined(separator: ",") // <- String.init(decimalStyle:)が呼ばれてしまう。String.init(decimalStyle:)を指定しないと呼ばれるべきでないのでは? ids.map { String($0) }.joined(separator: ",") // <- こうすれば、回避できる
3:04 AM
ちなみに同じ型の引数を持つやつを追加するとどうなるかなと思って以下を追加してみたら Ambiguous use of 'init' とエラーを返されて「引数ラベル見てないのか...?」となった次第です。これの実行環境はPlaygroundでした。 init(hoge int: Int) { self = String(int) }
Avatar
omochimetaru 1/18/2019 3:05 AM
ラベルのついた引数がある関数は String.init(decimalStyle:) って関数を指定できるけど (edited)
3:06 AM
引数が1つでラベルがついてない関数の場合、同じノリで指定しようとすると
3:06 AM
String.init() って記法になるけどこれだと呼び出しになっちゃうから、それができなくって
3:06 AM
名前だけの記法→ String.init になると、今度はこいつはラベル付きも含めたオーバーロード検索になるよね
3:07 AM
でもなんでそれambiguousエラーじゃなくてdecimalStyleの方に確定しちゃうんだろう
3:08 AM
init<T>(_ value: T) where T : LosslessStringConvertible これになってるっぽい?
3:08 AM
Genericな関数と通常の関数だから、decimalStyle:のほうが勝っちゃうのか
Avatar
花芽尋かすみ 1/18/2019 3:09 AM
ラベル付きも含めたオーバーロード検索になる
これは検索範囲が広く取られてしまうって話で合ってますか?
Avatar
omochimetaru 1/18/2019 3:10 AM
はい
Avatar
花芽尋かすみ 1/18/2019 3:10 AM
なるほど。そのうえでGenericな関数と通常の関数の間には、優先順位がある?👀
Avatar
omochimetaru 1/18/2019 3:10 AM
import Foundation extension String { init<I : SignedInteger>(decimalStyle int: I) { let formatter = NumberFormatter() formatter.numberStyle = .decimal self = formatter.string(from: Int(int) as NSNumber)! } } let ids = [89902,100238,123289] let a = ids.map(String.init).joined(separator: "|") // Ambiguous use of 'init'
3:11 AM
↑こうすればGeneric同士だから曖昧になってコンパイルエラーになった。
Avatar
花芽尋かすみ 1/18/2019 3:11 AM
なるほど
Avatar
omochimetaru 1/18/2019 3:11 AM
ジェネリックじゃなくて型がピタリと一致してる関数のほうが優先されます
3:11 AM
普段のオーバーロードでも。
Avatar
花芽尋かすみ 1/18/2019 3:11 AM
fmfm
Avatar
omochimetaru 1/18/2019 3:12 AM
でもこれはハマりそうですね・・・
Avatar
花芽尋かすみ 1/18/2019 3:14 AM
あくまで表示のためのString拡張と思って作ってたんですが、この例のようにAPIリクエストでids.map(String.init)している箇所があって、そこに作用があって一瞬ヒヤっとしました。 下手に拡張するより、変換用の別のやつを作った方が安全だった...
Avatar
omochimetaru 1/18/2019 3:14 AM
extension Int { func formatDecimalStyle() -> String { let formatter = NumberFormatter() formatter.numberStyle = .decimal return formatter.string(from: self as NSNumber)! } } let ids = [89902,100238,123289] let a = ids.map { $0.formatDecimalStyle() }.joined(separator: "|") print(a) // 89,902|100,238|123,289 let b = ids.map(String.init).joined(separator: "|") print(b) // 89902|100238|123289
3:14 AM
initを拡張しなければ未遂に回避できそう (edited)
Avatar
花芽尋かすみ 1/18/2019 3:14 AM
あー、こっちの書き方よさそう
Avatar
omochimetaru 1/18/2019 3:15 AM
map(String.init) ←おしゃれなコレが使えないけど、普段は value.formatDecimalStyle() って書けるので入力しやすいです
3:16 AM
でもこれを持ってしてinitを増やすのはバッドプラクティスだって言うのも早計だなあ どうするのがいいんだ・・・
🤔 1
3:18 AM
map(String.init) ←この書き方にオーバーロード誤爆のリスクがあることは意識しておいたほうが良さそうですね
Avatar
花芽尋かすみ 1/18/2019 3:20 AM
そうですね。 結構使うシーンあるので 意識しとこう レベルで対策するのはアレな気がしていて、どう対策すべきか悩ましい。
3:25 AM
ひとまず腑に落ちました。ありがとうございます🙇
Avatar
norio_nomura 1/18/2019 3:39 AM
static funcにしてids.map(String.formatDecimalStyle)とか。
Avatar
花芽尋かすみ 1/18/2019 3:43 AM
あー、なるほど
Avatar
@swift-4.2.4 -frontend -emit-syntax import Foundation public class TestFunctionDeclNoReturn { func twoArgumentNoReturn(argument1: Int, argument2: String) { } }
Avatar
{"kind":"SourceFile","layout":[{"kind":"CodeBlockItemList","layout":[{"kind":"CodeBlockItem","layout":[{"kind":"ImportDecl","layout":[null,null,{"tokenKind":{"kind":"kw_import"},"leadingTrivia":[{"kind":"Newline","value":1}],"trailingTrivia":[{"kind":"Space","value":1}],"presence":"Present"},null,{"kind":"AccessPath","layout":[{"kind":"AccessPathComponent","layout":[{"tokenKind":{"kind":"identifier","text":"Foundation"},"leadingTrivia":[],"trailingTrivia":[],"presence":"Present"},null],"presence":"Present"}],"presence":"Present"}],"presence":"Present"},null],"presence":"Present"},{"kind":"CodeBlockItem","layout":[{"kind":"ClassDecl","layout":[null,{"kind":"ModifierList","layout":[{"kind":"DeclModifier","layout":[{"tokenKind":{"kind":"kw_public"},"leadingTrivia":[{"kind":"Newline","value":2}],"trailingTrivia":[{"kind":"Space","value":1}],"presence":"Present"},{"kind":"TokenList","layout":[],"presence":"Present"}],"presence":"Present"}],"presence":"Present"},{"tokenKind":{"kind":"kw_class"},"leadingTrivia":[],"trailingTrivia":[{"kind":"Space","value":1}],"presence":"Present"},{"tokenKind":{"kind":"identifier","text":"TestFunctionDeclNoReturn"},"leadingTrivia":[],"trailingTrivia":[{"kind":"Space","value":1}],"presence":"Present"},null,null,null,{"kind":"MemberDeclBlock","layout":[{"tokenKind":{"kind":"l_brace"},"leadingTrivia":[],"trailingTrivia":[],"presence":"Present"},{"kind":"DeclList","layout":[{"kind":"FunctionDecl","layout":[null,null,{"tokenKind":{"kind":"kw_func"},"leadingTrivia":[{"kind":"Newline","value":1},{"kind":"Space","value":4}],"trailingTrivia":[{"kind":"Space","value":1}],"presence":"Present"},{"tokenKind":{"kind":"identifier","text":"twoArgumentNoReturn"},"leadingTrivia":[],"trailingTrivia":[],"presence":"Present"},null,{"kind":"FunctionSignature","layout":[{"kind":"ParameterClause","layout":[{"tokenKind":{"kind":"l_paren"},"leadingTrivia":[],"trailingTrivia":[],"presence":"Present"},{"kind":"FunctionParameterList","layout":[{"kind":"Function
Avatar
^ の結果についてわかる方答えてもらえると嬉しいです。 swift-syntaxで質問なのですが ^ の出力結果の jsoncomma の位置がおかしいなと思っているのですがあっていますか? bugっぽいならフォーラムあげてPRまで送るのやってみたいなと思っています おかしいと思っている場所 ... "kind": "FunctionParameter", "layout": [ ... { "id": 20, "tokenKind": { "kind": "comma" // elipsis の位置に commaが来ているのがおかしい }, "leadingTrivia": [], "trailingTrivia": [ { "kind": "Space", "value": 1 } ], "presence": "Present" }, null, // ここは default argument のlayoutだから `null` で正しい null // ここが trailing comma のはず ], "presence": "Present" }, ... 順番はここで確認した https://github.com/apple/swift/blob/master/utils/gyb_syntax_support/DeclNodes.py#L338 (edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
Kishikawa Katsumi 1/20/2019 3:51 AM
^ の「おかしいと思っている場所」のJSONと出力のJSONがちょっと違ってないですか?
3:53 AM
Ellipsis、は元のコードにないのでそれは無くて合ってると思います。
Avatar
layout: [...] の中に入る 子要素って Cursor の順番通り入っていないとおかしいのでは、と思っています ^ の質問は ... が含まれていない Syntax なのに ellipsis の場所に comma が入っていて、 (trailing) comma の場所が null なのがおかしいのでは、と思った質問でした
5:47 AM
^ でかいた僕が貼っている jsonlayout:[] の上下は結構削っていて、 ellipsis のところと comma を目立たせたかったのでそれ以前の layout の要素は削って貼ってあります
Avatar
omochimetaru 1/20/2019 5:48 AM
swiftcに渡してるソースコードには ellipsis が書いてある箇所があるってことですか?
Avatar
いや、このコードには ellipsis は無い、です(で答え方あってるかな) import Foundation public class TestFunctionDeclNoReturn { func twoArgumentNoReturn(argument1: Int, argument2: String) { } }
Avatar
omochimetaru 1/20/2019 5:50 AM
// elipsis の位置に commaが来ているのがおかしい ↑この 「elipsisの位置」の意味が、わからないんです。
5:51 AM
コードにelipsisが書いてないから。
Avatar
少し順序立てて質問の内容を整理したいのですが 例えば FunctionParameter "layout": だと https://github.com/apple/swift/blob/master/utils/gyb_syntax_support/DeclNodes.py#L317 この順番通りに layout が並ぶはずだと思っています。 Attributes(要素0) の次は FirstName(要素1) FirstName(要素1) の次は SecondName (要素2) って具合に。 それで、省略可能な要素n番目に関しては、 layout[n]null が代入されると思っています ellipsis が最後から数えると 3番目の要素になっているのですが、出力結果を見ると 最後から 3番目に入っている要素の tokenKind.kindcomma になっているのがおかしいのでは、っていう質問でした
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
5:59 AM
それで、省略可能な要素n番目に関しては
少し違った。省略可能で、省略した場合の要素n番目に関して、だ。
(edited)
5:59 AM
引用どうやってやるんだ
Avatar
omochimetaru 1/20/2019 6:00 AM
Elilipsisというのは引数のラベル名じゃなくって、
6:00 AM
SwiftSyntaxにおけるなんかの構造のメンバ名なんですね。勘違いしてました。
Avatar
たぶん 可変長引数の ... の記号を指している言葉なはず (edited)
Avatar
omochimetaru 1/20/2019 6:02 AM
...を現すっぽいですね
Avatar
Kishikawa Katsumi 1/20/2019 6:03 AM
そこでいうEllipsisはそうなんですけど、それはSwiftSyntaxは今のところ出さないんじゃないかな。
6:03 AM
それはEllipsisにはたぶん今のところならない
Avatar
norio_nomura 1/20/2019 6:03 AM
先のボットへ渡したソースに ... は無いし、ボットの出力にも ellipsis が無いので、???となってる。 https://ptpb.pw/uDno.txt/text/text
Avatar
Kishikawa Katsumi 1/20/2019 6:04 AM
それはEllipsisにはたぶん今のところならない
実装がそうなってないので。
6:04 AM
定義を可変長引数にしても、、、って意味です。
Avatar
https://github.com/apple/swift-syntax それはEllipsisにはたぶん今のところならない だと public struct FunctionParameterSyntax: Syntax, _SyntaxBase, Hashable { enum Cursor: Int { case attributes case firstName case secondName case colon case type case ellipsis case defaultArgument case trailingComma } Swift-Syntaxの Swiftコードに case ellipsis があるのはどういうことなんでしょう
SwiftPM package for SwiftSyntax library. Contribute to apple/swift-syntax development by creating an account on GitHub.
Avatar
Kishikawa Katsumi 1/20/2019 6:05 AM
定義上はそうで、後から実装が追いつくんじゃないですかね。
6:05 AM
推測ですけど。
Avatar
omochimetaru 1/20/2019 6:06 AM
最後から3番目がカンマっていうのがよくわからなくて
6:06 AM
今構造を追ってみたんですけど
Avatar
だとしても、 layout の最後に trailing comma が来ないのはおかしいと思っているので、実装漏れとかそういう具合な気がしていますね これがおかしい。っていうならフォーラムにあげようと思っているのですが。。
Avatar
omochimetaru 1/20/2019 6:07 AM
FunctionPArameterList の中に FunctionParameterが2つあって
👌 1
Avatar
Kishikawa Katsumi 1/20/2019 6:07 AM
Avatar
omochimetaru 1/20/2019 6:07 AM
1つ目のFunctionPArameterは Identifier, colon, SimpleTypeIdentifier, Comma
6:07 AM
2つめのFunctionParameterは Identifier, colon, SimpleTypeIndentifier
6:07 AM
となっているので
6:08 AM
( a : A, b: B ) の形で、特におかしくないと思いました。
Avatar
Kishikawa Katsumi 1/20/2019 6:08 AM
ちなみに可変長引数の定義だと ... は今のところ演算子として解釈される。
Avatar
omochimetaru 1/20/2019 6:09 AM
Child('Ellipsis', kind='Token', is_optional=True), Child('DefaultArgument', kind='InitializerClause', is_optional=True), Child('TrailingComma', kind='CommaToken', is_optional=True), ↑この3つが入るスロットは null, null, null になっているけど、 is_options = True なので、nullになるので良いのでは
Avatar
Kishikawa Katsumi 1/20/2019 6:09 AM
trailing comma も無いので出ないと思うんですけど、来るべきというのはどこからですか?
Avatar
もう少し大きめに json 貼ってdiscussionしている位置を合わせようと思っているので少しお待ちを
Avatar
omochimetaru 1/20/2019 6:09 AM
gistに張ると良いとおもます
Avatar
お、確かに
6:14 AM
swift-syntax-output. GitHub Gist: instantly share code, notes, and snippets.
swift-syntax-output. GitHub Gist: instantly share code, notes, and snippets.
6:14 AM
@omochimetaru さんが言っていた、第一引数ですね 1つ目のFunctionPArameterは Identifier, colon, SimpleTypeIdentifier, Comma
Avatar
Kishikawa Katsumi 1/20/2019 6:14 AM
swift-syntax-output. GitHub Gist: instantly share code, notes, and snippets.
Avatar
ふおおお、知らなかった
6:16 AM
↑この3つが入るスロットは null, null, null になっているけど、 is_options = True なので、nullになるので良いのでは つまり場所が違うのでこれは一旦議論から外す
6:19 AM
まずこれそもそものあるべき姿を確認しておきたいのですが、 layout: [] の情報は Syntaxの種類によって要素の数と要素の順番は決定されている。 っていうのは間違い無いですか?
Avatar
norio_nomura 1/20/2019 6:20 AM
ああ、質問の意図が分かったかも。
Avatar
ここが null なのは @escaping とうの Attribute が無いから https://gist.github.com/bannzai/0fae75994c61d9ecf8cfb440de003515#file-json-L206 ここの構造が存在するのは argument1 という引数ラベルが存在するから https://gist.github.com/bannzai/0fae75994c61d9ecf8cfb440de003515#file-json-L207 ここが null なのはラベルとfunc内部で使われる変数 が一緒だから https://gist.github.com/bannzai/0fae75994c61d9ecf8cfb440de003515#file-json-L216
swift-syntax-output. GitHub Gist: instantly share code, notes, and snippets.
swift-syntax-output. GitHub Gist: instantly share code, notes, and snippets.
swift-syntax-output. GitHub Gist: instantly share code, notes, and snippets.
6:21 AM
確認の意味は、^ って具合のことを言いたい (edited)
Avatar
Kishikawa Katsumi 1/20/2019 6:22 AM
なるほど。私も質問の意図は理解しました 😄
😄 1
6:22 AM
要素の数が決まってるかどうかは、どうなんでしょうねえ?
6:22 AM
聞いてみるしかない気がします。
Avatar
要素の数が決まってるかどうかは、どうなんでしょうねえ? 確かに。全てを追ったわけじゃ無いので憶測は入っている。 null 埋めで要素を enum で吐いているみたいだからそうだと思ってしまっていました
Avatar
Kishikawa Katsumi 1/20/2019 6:25 AM
私ならどうするかから推測すると、SwiftSyntaxはコンパイルエラーがある構文でもASTはできるので、数は決まってない、というのがありそうだとは思います。
👌 1
Avatar
norio_nomura 1/20/2019 6:27 AM
並び順や要素数が固定であることを期待したコードにしてしまうと、すぐに破綻しそうだ。
Avatar
Kishikawa Katsumi 1/20/2019 6:29 AM
@swiftbot --options='-frontend -emit-syntax' import Foundation public class TestFunctionDeclNoReturn { func twoArgumentNoReturn(argument1...: Int,,, argument2: String) { } }
🛠 1
Avatar
swiftbot BOT 1/20/2019 6:30 AM
Author icon
kishikawakatsumi
import Foundation public class TestFunctionDeclNoReturn { func twoArgumentNoReturn(argument1...: Int,,, argument2: String) { } }
Version:
swift-4.2.1-RELEASE
Output:
...
Error:
/usercode/main.swift:4:30: error: expected parameter name followed by ':' func twoArgumentNoReturn(argument1...: Int,,, argument2: String) { ^ /usercode/main.swift:4:48: error: unexpected ',' separator func twoArgumentNoReturn(argument1...: Int,,, argument2: String) { ^ /usercode/main.swift:4:49: error: unexpected ',' separator func twoArgumentNoReturn(argument1...: Int,,, argument2: String) { ^ /usercode/main.swift:4:5: warning: unknown declaration syntax exists in the source func twoArgumentNoReturn(argument1...: Int,,, argument2: String) { ^
6:30 AM
Avatar
Kishikawa Katsumi 1/20/2019 6:30 AM
例えば、^ はカンマとかむちゃくちゃですけどJSON自体は出力されて、見た目どおりのツリーになるので。
6:31 AM
ASTはSwiftSyntaxがギブアップしない限り元のソースコードによる。
Avatar
なるほど。失敗したパターンについては考慮できていなかったです。。 が、話題の発端の ^ で出力した json については正確に構文解析はできるべきなのでは、と考えています。
Avatar
norio_nomura 1/20/2019 6:33 AM
commaの位置自体はおかしくないのでは?
Avatar
あ、そういう風に捉えられるのか。ムムム。ちょっとお待ちをいくつか確認しよう
6:37 AM
commaの位置自体はおかしくないのでは?
っていうのはあれですよね。特定のキーワードにマッチしたものがあれば layoutは先頭から埋まっていく。っていう話ですよね
(edited)
6:38 AM
@swift-4.2.1 -frontend -emit-syntax import Foundation public class TestFunctionDeclDefaultArgument { func multipleArgument(argument1: Int = 1, argument2: String = "string") { } }
6:38 AM
やっちまった
6:38 AM
@swift-4.2.4 -frontend -emit-syntax import Foundation public class TestFunctionDeclDefaultArgument { func multipleArgument(argument1: Int = 1, argument2: String = "string") { } }
Avatar
{"kind":"SourceFile","layout":[{"kind":"CodeBlockItemList","layout":[{"kind":"CodeBlockItem","layout":[{"kind":"ImportDecl","layout":[null,null,{"tokenKind":{"kind":"kw_import"},"leadingTrivia":[{"kind":"Newline","value":1}],"trailingTrivia":[{"kind":"Space","value":1}],"presence":"Present"},null,{"kind":"AccessPath","layout":[{"kind":"AccessPathComponent","layout":[{"tokenKind":{"kind":"identifier","text":"Foundation"},"leadingTrivia":[],"trailingTrivia":[],"presence":"Present"},null],"presence":"Present"}],"presence":"Present"}],"presence":"Present"},null],"presence":"Present"},{"kind":"CodeBlockItem","layout":[{"kind":"ClassDecl","layout":[null,{"kind":"ModifierList","layout":[{"kind":"DeclModifier","layout":[{"tokenKind":{"kind":"kw_public"},"leadingTrivia":[{"kind":"Newline","value":2}],"trailingTrivia":[{"kind":"Space","value":1}],"presence":"Present"},{"kind":"TokenList","layout":[],"presence":"Present"}],"presence":"Present"}],"presence":"Present"},{"tokenKind":{"kind":"kw_class"},"leadingTrivia":[],"trailingTrivia":[{"kind":"Space","value":1}],"presence":"Present"},{"tokenKind":{"kind":"identifier","text":"TestFunctionDeclDefaultArgument"},"leadingTrivia":[],"trailingTrivia":[{"kind":"Space","value":1}],"presence":"Present"},null,null,null,{"kind":"MemberDeclBlock","layout":[{"tokenKind":{"kind":"l_brace"},"leadingTrivia":[],"trailingTrivia":[],"presence":"Present"},{"kind":"DeclList","layout":[{"kind":"FunctionDecl","layout":[null,null,{"tokenKind":{"kind":"kw_func"},"leadingTrivia":[{"kind":"Newline","value":1},{"kind":"Space","value":4}],"trailingTrivia":[{"kind":"Space","value":1}],"presence":"Present"},{"tokenKind":{"kind":"identifier","text":"multipleArgument"},"leadingTrivia":[],"trailingTrivia":[],"presence":"Present"},null,{"kind":"FunctionSignature","layout":[{"kind":"ParameterClause","layout":[{"tokenKind":{"kind":"l_paren"},"leadingTrivia":[],"trailingTrivia":[],"presence":"Present"},{"kind":"FunctionParameterList","layout":[{"kind":"Func
Avatar
テキストが出ない。。 #swiftbot-sandbox で事前に同じコードで試していたものがあったので、それを貼りますね https://ptpb.pw/BAs-.txt/text
Avatar
omochimetaru 1/20/2019 6:41 AM
自分のターミナルで $ swiftc -frontend -emit-syntax で出ますよ。
Avatar
ですね。一応同じもの見るためにここでやっとこうかなと思った感じでした
6:43 AM
with default argument. GitHub Gist: instantly share code, notes, and snippets.
Avatar
omochimetaru 1/20/2019 6:43 AM
手元ではいたのをどっかに貼るのが100%齟齬がないです
Avatar
齟齬と言われると今どこが気になりました? swiftbotでやっても変わらないのかなと思っていました。この場であればどのswiftのバージョンで吐いたかもわかるから利点もあるのかなと思っています!
6:47 AM
https://gist.github.com/bannzai/dfc79a80890e523ee193afed9afb7b03#file-json-L251 それでここを見ると
commaの位置自体はおかしくないのでは? っていうのはあれですよね。特定のキーワードにマッチしたものがあれば layoutは先頭から埋まっていく。っていう話ですよね
今度はここが null じゃなくて一つ次の "kind": "InitializerClause", が来るはずなのでは、と思っている感じです
with default argument. GitHub Gist: instantly share code, notes, and snippets.
6:48 AM
今確認したらここも 最後から3番目か
Avatar
omochimetaru 1/20/2019 6:48 AM
齟齬と言われると今どこが気になりました?
すでにたくさんbotの投稿があるので、どれを指してるのかよくわからなくなってきたので・・・
Avatar
あああ、そこは。。。ある。 これ gist に実行元コードも貼るのがいい気がしますね
Avatar
omochimetaru 1/20/2019 6:50 AM
今のgistのコードは import Foundation public class TestFunctionDeclDefaultArgument { func multipleArgument(argument1: Int = 1, argument2: String = "string") { } } ↑これですか?
Avatar
それですね!このコメントの内容のコードは @omochimetaru さんが今貼ってくれたコードです!
Avatar
omochimetaru 1/20/2019 6:53 AM
今度はここが null じゃなくて一つ次の "kind": "InitializerClause", が来るはずなのでは、と思っている感じです
6:54 AM
FunctionParameterのchildrenスロットは Attr, FirstName, SecondName, Colon, Type, Ellipsis, DefaultARgu, TrailingComma であるのに対して
6:55 AM
対応箇所は argument1: Int = 1, だから Attrなし FirstName=argument1, SecondNameなし, Colon=:, Type=Int, Elipsisなし, DefaultArg = 1, TarilingComma=,
6:55 AM
となることが期待されて
6:55 AM
実際JSONが
6:55 AM
そうなってるように見えますね。
Avatar
YES!!なってます!言葉がややこしかったかもしれないのですが、僕はそれが正解だと思っています!
Avatar
omochimetaru 1/20/2019 6:56 AM
nullがあるポイントは、attrの[0], secondNameの[2], Elipsisの[5]。
👌 1
6:57 AM
そうすると、emit-syntaxの出力も、期待通りですが、疑問点はなんでしたっけ
Avatar
こっちの gist での https://gist.github.com/bannzai/0fae75994c61d9ecf8cfb440de003515#file-json-L205-L261 nullがあるポイントは attrの[0], secondNameの[2]、 Ellipsisの[5], DefaultArgument[6] だと思っています!
swift-syntax-output. GitHub Gist: instantly share code, notes, and snippets.
6:58 AM
syntaxを解析する元のコードは一番下に書いてある
Avatar
omochimetaru 1/20/2019 6:59 AM
あ、ほんとうだ
6:59 AM
ElipsisとDefaultArguのnullが無いまま
6:59 AM
commaが来ている?
Avatar
norio_nomura 1/20/2019 6:59 AM
nullの位置は無視した方が良いのでは…
Avatar
omochimetaru 1/20/2019 7:00 AM
末尾に2つあるnullはなんだろう?
7:00 AM
[5] = TarilingComma, [6] = Elipsisのnull?, [7] = DefaultARgのnull?
7:00 AM
って感じに見えますね。
Avatar
お、そういうことになるのか。そこまではまだ追ってないし想像もできていませんでした。
Avatar
omochimetaru 1/20/2019 7:02 AM
あ、いや?
7:02 AM
なんかいろいろ無いね (edited)
7:02 AM
[0] = null ( attr? [1] = identifier (FirstName [2] = null (SecondName [3] = colon [4] = TypeID [5] = comma [6] = null, [7] = null (edited)
7:03 AM
JSONを目で見た感じこうなってる
7:04 AM
SwiftPM package for SwiftSyntax library. Contribute to apple/swift-syntax development by creating an account on GitHub.
7:04 AM
-emit-syntaxのJSONは、↑のSwift言語で書かれてるSwiftSyntaxでパースしてSwiftのオブジェクトになるので
7:04 AM
該当箇所のパースロジックを見てみると何かわかりそう
7:06 AM
SwiftPM package for SwiftSyntax library. Contribute to apple/swift-syntax development by creating an account on GitHub.
7:06 AM
↑masterだと今実装方法が変わっちゃってるとおもうんで4.2ブランチのだけど
7:06 AM
gybでテンプレート化されてて全く読めねえw
Avatar
norio_nomura 1/20/2019 7:07 AM
nullではない要素の順番が合ってて、欠けていなければ十分では…
Avatar
omochimetaru 1/20/2019 7:07 AM
順番が前後してるように見えませんか?
7:08 AM
本来commaはtrailingCommaなので[7]に欲しい。
7:08 AM
SwiftPM package for SwiftSyntax library. Contribute to apple/swift-syntax development by creating an account on GitHub.
7:08 AM
↑このスナップショットだとgyb処理した後だ
Avatar
やったぜ
Avatar
omochimetaru 1/20/2019 7:10 AM
// ###sourceLocation(file: "/Users/alex/Documents/swift-src/swift-syntax/Sources/SwiftSyntax/SyntaxNodes.swift.gyb", line: 140) public var ellipsis: TokenSyntax? { let child = data.cachedChild(at: Cursor.ellipsis) // ###sourceLocation(file: "/Users/alex/Documents/swift-src/swift-syntax/Sources/SwiftSyntax/SyntaxNodes.swift.gyb", line: 143) if child == nil { return nil } // ###sourceLocation(file: "/Users/alex/Documents/swift-src/swift-syntax/Sources/SwiftSyntax/SyntaxNodes.swift.gyb", line: 145) return makeSyntax(root: _root, data: child!) as? TokenSyntax }
7:10 AM
func cachedChild<CursorType: RawRepresentable>( at cursor: CursorType) -> SyntaxData? where CursorType.RawValue == Int { return cachedChild(at: cursor.rawValue) }
7:10 AM
おや?
7:11 AM
nullスキップとか考慮しないで、普通にIndexでアクセスしてるように見える
7:11 AM
これ、SwiftAPIのSwiftSyntaxから読み取ったら、trailing commaのデータを、elipsisとしてデコードしようとして
7:11 AM
クラッシュするかも?
Avatar
そう。実はそこらへんはなんとなく確認していて、 Optional<SuyntaxData> がはいる Arrayになっているっぽいんですよね
7:12 AM
あれ、嘘ついたかも (edited)
Avatar
omochimetaru 1/20/2019 7:12 AM
このvar ellipsisは、 public struct FunctionParameterSyntax: Syntax, _SyntaxBase, Hashable のメンバです
👌 1
7:14 AM
今SwiftSyntaxが、高速化アップデートで、-emit-syntaxの出力JSONをパースするのを辞めて、新しいC-APIでSwiftとマッピングするように変わったので
7:14 AM
このバグがもしバグだったとしても、根本的に実装方式が変わって水に流れるかもしれない
Avatar
norio_nomura 1/20/2019 7:15 AM
そんな、順序依存のコードになってるとは信じられないけど…
Avatar
omochimetaru 1/20/2019 7:16 AM
実験してみましょっか
Avatar
このバグがもしバグだったとしても、根本的に実装方式が変わって水に流れるかもしれない
ほほん。そうなんですね。ただこれテスト漏れでもあるのでやっぱりおかしいならフォーラムにはあげる気概
7:17 AM
(実装漏れかなんかだとまだ思っている)
Avatar
omochimetaru 1/20/2019 7:18 AM
まあ、json実装の -emi-syntaxが壊れてるのは事実ですからね
7:23 AM
ビルドできねえ・・・
7:23 AM
let package = Package( name: "SwiftSyntax-issue-ellipsis", products: [ .executable(name: "SwiftSyntax-issue-ellipsis", targets: ["SwiftSyntax-issue-ellipsis"]), ], dependencies: [ .package(url: "https://github.com/apple/swift-syntax.git", .revision("swift-4.2-DEVELOPMENT-SNAPSHOT-2018-08-25-a")), ], targets: [ .target(name: "SwiftSyntax-issue-ellipsis", dependencies: ["SwiftSyntax"]), .testTarget(name: "SwiftSyntax-issue-ellipsisTests", dependencies: ["SwiftSyntax-issue-ellipsis"]), ] )
7:23 AM
なんかちがうかな
7:24 AM
swift-DEVELOPMENT-SNAPSHOT-2018-08-25-a こっちはビルドできた。
7:25 AM
4.2 08/25はこわれてる気がする・・・
Avatar
これがStableなのかなと思いました
7:26 AM
SwiftPM package for SwiftSyntax library. Contribute to apple/swift-syntax development by creating an account on GitHub.
Avatar
omochimetaru 1/20/2019 7:26 AM
あ〜
7:26 AM
SwiftPM package for SwiftSyntax library. Contribute to apple/swift-syntax development by creating an account on GitHub.
7:26 AM
.package(url: "https://github.com/apple/swift-syntax.git", .exact("0.40200.0")), こうか
Avatar
norio_nomura 1/20/2019 7:33 AM
SwiftSyntaxはswift.orgで配布されてるswift-4.2.1-RELEASEに含まれてるのでは?
Avatar
omochimetaru 1/20/2019 7:34 AM
何もしなくてもimportできるんですっけ
Avatar
norio_nomura 1/20/2019 7:38 AM
出来る。 $ xcrun --toolchain org.swift.42120181030a swift -frontend -repl -sdk `xcrun --show-sdk-path --sdk macosx` *** You are running Swift's integrated REPL, *** *** intended for compiler and stdlib *** *** development and testing purposes only. *** *** The full REPL is built as part of LLDB. *** *** Type ':help' for assistance. *** (swift) import SwiftSyntax (swift) :print_module SwiftSyntax import Darwin import Foundation struct AttributeListSyntaxIterator : IteratorProtocol { typealias Element = AttributeSyntax let collection: <null> var index: <null> init(collection: AttributeListSyntax) mutating func next() -> AttributeListSyntaxIterator.Element? } … extension ValueBindingPatternSyntax { init(_ build: (inout ValueBindingPatternSyntaxBuilder) -> Void) } (swift)
Avatar
omochimetaru 1/20/2019 7:38 AM
なるほど・・・、まあ、tag指定しておいたほうが、先方環境で変な事がなさそうなので、これでいきます
Avatar
norio_nomura 1/20/2019 7:39 AM
swiftSwiftSyntaxも、swift-4.2.1-RELEASEになるのに?
Avatar
omochimetaru 1/20/2019 7:40 AM
例えば5.0のswiftで実行したら問題が生じないとなると
7:40 AM
あとでよくわからなくなると思って。
Avatar
norio_nomura 1/20/2019 7:43 AM
ああ、5.0はSwiftSyntax.swiftmoduleとか無いからインポートできないな。
Avatar
omochimetaru 1/20/2019 7:49 AM
できた!!
👀 1
7:49 AM
ちょいまちよ
7:50 AM
let sourceFile = try SyntaxTreeParser.parse(codePath) let blocks = sourceFile.children.compactMap { $0 as? CodeBlockItemListSyntax }.first! let block: CodeBlockItemSyntax = blocks.first! let classDecl = block.children.compactMap { $0 as? ClassDeclSyntax }.first! let funcDecl = classDecl.members.members.children.compactMap { $0 as? FunctionDeclSyntax }.first! let funcSig = funcDecl.children.compactMap { $0 as? FunctionSignatureSyntax }.first! let paramClause = funcSig.children.compactMap { $0 as? ParameterClauseSyntax }.first! let params = paramClause.children.compactMap { $0 as? FunctionParameterListSyntax }.first! let param0: FunctionParameterSyntax = params[0] print(param0) if let ellipsis = param0.ellipsis { print("---ellipsis---") print(type(of: ellipsis)) print(ellipsis) print("---") } else { print("no ellipsis") } if let trailingComma = param0.trailingComma { print("---trailing comma---") print(type(of: trailingComma)) print(trailingComma) print("---") } else { print("no trailing comma") }
7:50 AM
ccc: Int, ---ellipsis--- TokenSyntax , --- no trailing comma Program ended with exit code: 0
7:50 AM
ellipsis扱いで , が来て、 trailing commaが無いことになった。
7:52 AM
Contribute to omochi/SwiftSyntax-issue-ellipsis development by creating an account on GitHub.
Avatar
あ、それが今まさに SwiftSyntax使って作っていたツールで起きていた問題ですです。(先に言え) ellipsis でアクセスして , が来るのが、アレってなってから仕様を追ってたんだ
Avatar
omochimetaru 1/20/2019 7:52 AM
↑cloneしてswift runで再現できます
👌 1
7:54 AM
bannzaiさん報告するならこのリポジトリを参照してくれていいですよ
7:54 AM
面倒だったら僕が報告しても良いです
Avatar
まじか。Special thanks!! 一度やってみたかったので僕がやります!
Avatar
omochimetaru 1/20/2019 7:55 AM
OKです、報告先はこちらが良いと思います→ https://bugs.swift.org
👌 1
Avatar
norio_nomura 1/20/2019 8:00 AM
なるほど、確かにIndexでアクセスしているのですね…
Avatar
omochimetaru 1/20/2019 8:03 AM
あるtokenの情報は固定スロットのプロパティになっていて、可変長な要素は一回り外側で扱う感じの設計に見えますね
Avatar
norio_nomura 1/20/2019 8:23 AM
SwiftSyntaxの実装を初めてマトモに見たけど、何故こんな実装に…
Avatar
ふああああああああ。Markdown効かないのか。初めてのbug?報告。皆さんありがとうございました! 😊 https://bugs.swift.org/browse/SR-9710
👍 4
Avatar
omochimetaru 1/25/2019 5:59 AM
ABI安定化はじまったな
Avatar
omochimetaru 1/28/2019 6:08 AM
https://forums.swift.org/t/strict-value-semantics/19677 strict value semanticsという新概念を試しに実装したらしい 値型が参照を保有できないようにして、副作用の無い関数の検証などを可能とするらしい 最適化や、将来的には並列処理サポートの役に立つとか。
Hello, In my free time and as a part of a larger research project, I’ve been maintaining a proof-of-concept patch that implements strict value semantics. At this point in my project, I’d like to see what it would take to get strict value semantics integrated into mainlin...
6:08 AM
Contribute to davezarzycki/swift development by creating an account on GitHub.
Avatar
enumは値型と参照型の二通りできるのかな
12:13 AM
現実的にはアノテーションつけるなりして段階を踏めるのが良さそう
Avatar
enumは値型だからsemanticsもvalueだと思うけど、デフォルトのsemanticsを変更できる機能を考えてるって書いてある
Avatar
indirectの扱い?
Avatar
structの対はclass使うでいいんですがenumは無理、Optionalとか困る
Avatar
Strict value types can pass/return/hold reference types but strict value types cannot call reference type members/getters/setters/etc. Thus strict value semantics are preserved, and popular generic value types continue to work (collections, Optional, etc).
1:01 AM
struct GeneralRefInValError { var c : C func foo() -> () -> V { // expected-error@+1 {{using reference semantic closure in a context expecting a value semantic closure}} return c.fn } }
1:02 AM
Casually speaking, strict value semantics means that value types “cannot” use reference semantics.
1:02 AM
「値型が参照型を持てない」は間違いだった。 「値型がreference semanticsを使えない」だ。
Avatar
norio_nomura 1/29/2019 5:59 AM
#swift-contrib で話してた、String.IndexencodedOffsetdeprecatedにする提案が来てた。 https://forums.swift.org/t/se-0241-explicit-encoded-offsets-for-string-indices/19929
The review of SE-0241: Explicit Encoded Offsets for String Indices begins now and runs through Sunday, February 3rd, 2019. This is a very late-breaking proposal which we are considering for Swift 5. Reviews are a vital part of the Swift evolution process. All review feedbac...
Avatar
omochimetaru 1/29/2019 6:18 AM
レビュー期間短め
6:20 AM
イントロで野村さんの報告にリンクありますね
Avatar
norio_nomura 1/29/2019 6:26 AM
ちゃんとswift-5.0-RELEASEへ入れられる様に急いでくれるみたいで良かった。
Avatar
あたらしいAPIはoffsetって概念をはっきりさせて、indexとの相互変換にviewを噛ませる感じですね
11:01 AM
自分のコードでもCとの境界で同じ事やってる部分が少しわかりやすくなりそう https://github.com/omochi/TMSyntax/blob/3e55117e889d24dc561596f9acea480573e46d7d/Sources/TMSyntax/Regex/OnigmoAPI.swift#L117
WIP. Contribute to omochi/TMSyntax development by creating an account on GitHub.
Avatar
omochimetaru 1/31/2019 5:25 PM
Hello Swift Community, The review of SE-0240 "Ordered Collection Diffing" ran from January 14...22, 2019. The review thread is available here. The proposal is accepted with modifications, specifically: The algorithm's semantic guarantees have been weakened to specify that ...
5:25 PM
diffが入るのが決まった
Avatar
おお
6:22 PM
これ入るとTableViewの体験がObjCとSwiftで乖離してくるのかな
6:23 PM
UIKitのAPIレベルで (edited)
Avatar
omochimetaru 1/31/2019 6:26 PM
Collectionの拡張だからUIKitは変わらないよ
6:26 PM
差分をアニメーション付きでコミットとかは作りやすくなるかも
Avatar
UIKitはこれを使ったAPIを提供しないのかな、そのうちするんじゃないかと思うのだけど
Avatar
omochimetaru 1/31/2019 6:29 PM
今ってデータの要素に関してはUIKitは感知していなくて
6:29 PM
Cellに自分で表示するようになってるから
6:29 PM
データの差分をUITableViewに与える形のAPIがどうなるのか想像つかない
Avatar
omochimetaru 2/2/2019 12:36 PM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
12:37 PM
Substring.withCStringすると一度Stringにコピーされちゃうっぽい・・・
12:38 PM
String + Range<String.Index> を元にして自分でポインタをオフセットしたほうが良いって事になっちゃう
Avatar
norio_nomura 2/2/2019 2:23 PM
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.
2:24 PM
元と違う範囲を持つなら、null terminationを追加する必要があるからコピーも仕方ないのでは。
2:25 PM
あいや、元Stringがnull terminationを持ってて、Substringの末尾が元Stringの末尾と同じになる場合にもコピーは回避して欲しいかな。
Avatar
omochimetaru 2/2/2019 3:02 PM
ああ、String.initの中にsubstringの場合の最適化は入っているんですね。
3:02 PM
たしかに途中で終わる場合にnullを入れたいから無理なのか。
3:03 PM
今使ってるライブラリが、Cブリッジはしてるけど、null terminationは特に求められていないので(start pointerとend pointerを渡すAPI)
3:03 PM
cString系のAPIを使おうとしているのが筋が悪いのかな
3:04 PM
でも、.utf8: UTF8View 経由だと、結局ArrayにコピーしてからwithUnsafePointerみたいな経路になりそうなんですよね (edited)
Avatar
norio_nomura 2/2/2019 3:05 PM
Swift 5からはString.UTF8View.withContiguousStorageIfAvailable(_:)を使う。
Avatar
omochimetaru 2/2/2019 3:06 PM
めっちゃそれっぽい名前のメソッド!!
3:06 PM
Swift4.2以前は等価なものは無かったんですか?
Avatar
norio_nomura 2/2/2019 3:08 PM
Swift 4.xはコピー発生は諦めて、String.utf8CString.dropLast().withUnsafeBytes(_:)を使うかな。
Avatar
omochimetaru 2/2/2019 3:10 PM
なるほど。
Avatar
norio_nomura 2/2/2019 3:10 PM
A Sweet and Swifty YAML parser. Contribute to jpsim/Yams development by creating an account on GitHub.
Avatar
omochimetaru 2/2/2019 3:11 PM
Swift5が来てからパフォーマンス最適化する方針にします。ありがとうございます。
Avatar
norio_nomura 2/2/2019 3:13 PM
どうせSwift 4.xまでは内部UTF-16だしね。
3:19 PM
withContiguousStorageIfAvailable(_:)nilを返した場合に対応しなければいけないから、Swift 4.x向けに常にnilを返すwithContiguousStorageIfAvailable(_:)を定義しておけば、Swift 5では自動的に最適化されるコードを書けるよ。 (edited)
Avatar
omochimetaru 2/2/2019 7:41 PM
どうせSwift 4.xまでは内部UTF-16だしね
そうなんですよね。 IfAvailableって用意できない場合はコピー/トランスコードしてくれるって意味だと思ったら、nilで何もしないから自分でやるのかw
Avatar
norio_nomura 2/4/2019 12:25 PM
swift-4.2.2-RELEASEが来そう。まだtoolchainはダウンロード出来ない。 https://github.com/apple/swift/releases/tag/swift-4.2.2-RELEASE
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
https://swift.org/blog/abi-stability-and-more/ 今週3つ目の Swift.org ブログ記事
It has been a longstanding goal to stabilize Swift’s ABI on macOS, iOS, watchOS, and tvOS. While a stable ABI is an important milestone for the maturity of any language, the ultimate benefit to the Swift ecosystem was to enable binary compatibility for apps and libraries. ...
Avatar
norio_nomura 2/8/2019 3:08 AM
サードパーティライブラリのバージョンをコード内でチェック出来るようにする仕組みは、将来入ったりしないのかな?>Library Evolution Support (edited)
3:09 AM
C系だとマクロを使えるけど、SwiftだとcanImportくらいしか無いよね。
3:11 AM
Avatar
おーたしかに、今のところ知らないです。是非Jordanに聞いてみてほしい。
Avatar
norio_nomura 2/8/2019 3:17 AM
canImportがモジュール内の型やシンボルに使えると活用できるのだけど、現状はモジュールまでしかチェック出来ない。 @swift-4.2.4 #if canImport(SwiftBacktrace.enablePrettyStackTrace) import SwiftBacktrace enablePrettyStackTrace() #endif (edited)
Avatar
swift42 BOT 2/8/2019 3:17 AM
exit status: 1 with stderr:<stdin>:1:5: error: unexpected platform condition argument: expected identifier #if canImport(SwiftBacktrace.enablePrettyStackTrace) ^ (edited)
Avatar
norio_nomura 2/8/2019 3:20 AM
あー、ランタイムチェックが必要だからcanImportではダメか。
3:26 AM
将来Swift 6で新規にstdlibへAPIが追加されたとして、それを使ったアプリを実行できるかどうかのチェックは、deployment targetでされる様になるのかな。
3:30 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
3:32 AM
// Client code @available(Magician 1.5) class CrystalBallView : MagicView { /*...*/ } func scareMySiblings() { if #available(Magician 1.2) { summonDemons() } else { print("BOO!!") } }
Avatar
norio_nomura 2/13/2019 6:12 AM
5.0でStringProtocolIndex周りにconstraintsが増えて使いやすくなった。 4.2.2: protocol StringProtocol : BidirectionalCollection, Comparable, ExpressibleByStringLiteral, Hashable, LosslessStringConvertible, TextOutputStream, TextOutputStreamable where Self.Element == Swift.Character, Self.SubSequence : StringProtocol { associatedtype UTF8View : Collection where Self.UTF8View.Element == Swift.UInt8 associatedtype UTF16View : BidirectionalCollection where Self.UTF16View.Element == Swift.UInt16 associatedtype UnicodeScalarView : BidirectionalCollection where Self.UnicodeScalarView.Element == Swift.Unicode.Scalar 5.0: protocol StringProtocol : BidirectionalCollection, Comparable, ExpressibleByStringInterpolation, Hashable, LosslessStringConvertible, TextOutputStream, TextOutputStreamable where Self.Element == Swift.Character, Self.Index == Swift.String.Index, Self.StringInterpolation == Swift.DefaultStringInterpolation, Self.SubSequence : StringProtocol { associatedtype UTF8View : Collection where Self.UTF8View.Element == Swift.UInt8, Self.UTF8View.Index == Swift.String.Index, Self.SubSequence.UTF8View.Index == Swift.String.Index associatedtype UTF16View : BidirectionalCollection where Self.UTF16View.Element == Swift.UInt16, Self.UTF16View.Index == Swift.String.Index, Self.SubSequence.UTF16View.Index == Swift.String.Index associatedtype UnicodeScalarView : BidirectionalCollection where Self.UnicodeScalarView.Element == Swift.Unicode.Scalar, Self.UnicodeScalarView.Index == Swift.String.Index, Self.SubSequence.UnicodeScalarView.Index == Swift.String.Index associatedtype SubSequence = Swift.Substring
Avatar
omochimetaru 2/13/2019 6:13 AM
お。ちょうどそれこの前気になったやつかな? StringProtocolの方だと String.Index == String.UTF8View.Index == String.UTF16View.Index ... が無かった。
Avatar
structのmutableプロパティがデフォルト値を持つ場合は、自動生成されるイニシャライザのパラメータにもデフォルト値を持たせる提案。 https://forums.swift.org/t/se-0242-synthesize-default-values-for-the-memberwise-initializer/20618 これは欲しいと思ったことが何度もある。
The review of SE-0242: Synthesize default values for the memberwise initializer begins now and runs through February 26, 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 f...
Avatar
omochimetaru 2/19/2019 2:16 AM
わかる
2:17 AM
これがあるからinitの自動生成ほぼ頼って無くて書き下した上でデフォルト値をinitの方に書きがちだった
2:18 AM
ディスカッションだとなんかいろいろ指摘があって素直な流れじゃなかった気がするけどReview入したんですね
Avatar
bugs.swift.orgへ登録したFeature Requestを基にpitchとかしてもらえるの、とても助かる。 https://forums.swift.org/t/pitch-string-gaps-and-missing-apis/20984
SE pull request and implementation. String Gaps and Missing APIs Proposal: SE-NNNN Authors: Michael Ilseman Review Manager: TBD Status: Pitched Implementation: apple/swift#22869 Bugs: SR-9955 Introduction String and associated types are missing trivial and obvious func...
Avatar
omochimetaru 2/28/2019 9:35 AM
There is nothing about opaque result types that make them unique in this respect from any other generic or existential context where the concrete type is unknown. Right now, AnyObject can be used to consorting to reference semantics. Perhaps in the future we will be able to...
9:35 AM
I think a subset of this proposal should be ready for review soon.
9:35 AM
opaque result typeのreviewが近いらしい
9:36 AM
protocol Shape { ... } func translucentRectangle() -> opaque Shape { ... }
9:36 AM
opaqueじゃなくてsomeはどうかなあ、だって
Avatar
norio_nomura 3/3/2019 11:27 AM
バイナリ配布をしないパッケージで@inlinable, @usableFromInlineを使ってはいけない場合ってのはあるのだろうか? https://github.com/apple/swift-evolution/blob/master/proposals/0193-cross-module-inlining-and-specialization.md
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
norio_nomura 3/5/2019 2:38 AM
@inlinableを付けない方が速くなるパターンを見つけたかも。
Avatar
omochimetaru 3/5/2019 2:39 AM
インライン化されると逆に遅くなるケースですか?
Avatar
norio_nomura 3/5/2019 2:42 AM
モジュールで公開するAPIが@inlinableを付けたジェネリックメソッドで、それがstdlib内のプロトコルを使って実装されてると、stdlib内のプロトコルがモジュールを使う側でspecializeされなくて、結果的に遅くなる。
2:43 AM
@inlinableを外すと、元のモジュール内でstdlibのプロトコルがspecializeされて速くなる。
Avatar
omochimetaru 3/5/2019 2:43 AM
stdlib内のプロトコルって、たとえば<S: Sequence>でも該当しますね
Avatar
norio_nomura 3/5/2019 2:43 AM
そう。
Avatar
omochimetaru 3/5/2019 2:43 AM
stdlib内のプロトコルがモジュールを使う側でspecializeされなくて、
なんでだろ?
2:44 AM
inline化された後でspecializeされない?
2:45 AM
条件がそれだけだったら結構踏んでしまいそう。
Avatar
norio_nomura 3/5/2019 2:46 AM
再現するプロジェクトを作ってみるかな…
Avatar
norio_nomura 3/5/2019 3:20 AM
Contribute to norio-nomura/InlinableTest development by creating an account on GitHub.
Avatar
norio_nomura 3/5/2019 3:28 AM
swift test -c releasetestInlined() average: 0.062 testNotInlined() average: 0.001 になる。
Avatar
norio_nomura 3/5/2019 4:10 AM
ジェネリックメソッドの呼び出しがspecializeされてるかどうかを簡単に確認する方法ってあるのかな?
Avatar
omochimetaru 3/5/2019 6:57 AM
IRを読むしか無さそう
6:58 AM
lower stageのSILを出力する方法があると嬉しいな。
Avatar
norio_nomura 3/5/2019 9:36 AM
$ swift test -c release -Xswiftc -save-optimization-record -Xswiftc -save-optimization-record-path -Xswiftc - とするとspecialized出来たかどうかを、各メソッド毎に出力してくれるぽい。 (edited)
9:37 AM
--- !Missed Pass: sil-inliner Name: sil.NoInlinedCost DebugLoc: File: /Users/norio/github/InlinableTest/Sources/InlinableTest/InlinableTest.swift Line: 17 Column: 29 Function: 'MyStruct.inlinedRanges<A>(_:)' Args: - String: 'Not profitable to inline function ' - Callee: '"specialized InlinableTest.RangeManager.ranges<A>(for:)"' DebugLoc: File: /Users/norio/github/InlinableTest/Sources/InlinableTest/InlinableTest.swift Line: 48 Column: 10 - String: ' (cost = ' - Cost: '72' - String: ', benefit = ' - Benefit: '40' - String: ')' ...
9:39 AM
どうやら@usableFromInlineなジェネリックメソッドを@inlinableなメソッドでspecialize出来ていないぽい。 (edited)
Avatar
omochimetaru 3/5/2019 9:41 AM
おお、save-optimization-recordいいですね
Avatar
norio_nomura 3/5/2019 10:09 AM
specialize出来ていなかった@usableFromInlineなジェネリックメソッドに@_specialize(where C==Range<Int>)と付けると、それを呼び出す@inlinableなメソッドもspecializeされる様になった。
10:10 AM
これはバグなのか仕様なのか。
Avatar
norio_nomura 3/5/2019 11:03 AM
どうやら@inlinableなメソッド内で直接stdlibのジェネリックなメソッドやプロトコルを使う分には問題ないらしい。
Avatar
norio_nomura 3/5/2019 11:43 AM
しかし、やはりジェネリックメソッドは@inlinableを付けない方が速いな。
Avatar
norio_nomura 3/5/2019 11:29 PM
Hi Swift Community, The review of SE-0244: Opaque Result Types begins now and runs through March 15, 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 your feedback pri...
Avatar
omochimetaru 3/6/2019 1:52 AM
Avatar
some Foo を返す関数を受ける変数の型は明示的に記述できない?
2:03 AM
変数の型として some Foo は書けない?
2:04 AM
書けても意味不明か。
2:05 AM
まだ Proposal 途中までしか読んでないけど↓になるという理解で正しい? func foo1() -> some Foo { return Foo1() } func foo2() -> some Foo { return Foo2() } var foo = foo1() foo = foo2() // コンパイルエラー
Avatar
これ実用上はassoctypeのあるprotocolのexistentialの代用という理解なんだけどあってるかしら (edited)
2:07 AM
むしろ本質的にそれなのかなぁ
Avatar
existential 的な使い方はできないんじゃないでしょうか。
Avatar
omochimetaru 3/6/2019 2:07 AM
existentialの回避じゃない?
Avatar
ふむー
Avatar
なので、↑のコンパイルエラーになるんだと思ってます。
Avatar
omochimetaru 3/6/2019 2:08 AM
まだ最新提案を読んでないけど
2:08 AM
やりたいのは
2:08 AM
ArrayとかLazyCollectionとかで、func prefix()とか対応しようとすると
Avatar
無駄に詳細になりすぎていた記述を必要最小限なレベルに簡易化したいということで、
2:09 AM
何かできることが増えるというものではないんだと思ってます。
Avatar
omochimetaru 3/6/2019 2:09 AM
理想のロジックを提供するためには専用のPrefixProxy型みたいなのが必要になっちゃって
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
2:09 AM
あった
Avatar
One could compose these transformations by using the existential type Shape instead of generic arguments, but doing so would imply more dynamism and runtime overhead than may be desired.
Avatar
omochimetaru 3/6/2019 2:10 AM
抽象的に書きたいっていうのと、具体的な型を書き下さないとオーバーヘッドが産まれる、っていう2つの矛盾する要求を解消するために
Avatar
anyに対してのsomeは解りやすいな
Avatar
omochimetaru 3/6/2019 2:11 AM
コンパイラが追跡できる限り具体的な型に展開されるが、コードのインターフェースとしては抽象的で、モジュール境界とかでは自動でexistentialみたいになる
2:11 AM
みたいなもん?
Avatar
つまりこれはあれだ一般的なexistentialに対してopenedな型だ
2:11 AM
@ukitaka 後で助けてくれ
Avatar
おや
2:12 AM
The implementation of a function returning an opaque type must return a value of the same concrete type T from each return statement, and T must meet all of the constraints stated on the opaque type.
(edited)
2:13 AM
そもそも↓がエラーになりそう。 func foo1() -> some Foo { return Foo1() } func foo2() -> some Foo { return Foo2() }
Avatar
omochimetaru 3/6/2019 2:13 AM
え、なぜです?
2:14 AM
each return statements は 1つのfuncの中でのことだと思います。
Avatar
エラーになるのは、 func foo() -> some Foo { if condition { return Foo1() } else { return Foo2() } } みたいなやつだと思いますよ。
🙏 1
Avatar
ああ
2:15 AM
読み違えてた
2:15 AM
びっくりしました。
2:15 AM
return "a string" だけ見てその前の行を見てなかった。
Avatar
omochimetaru 3/6/2019 2:19 AM
Future Directionsのopaque type alias面白いな
2:19 AM
public typealias LazyCompactMapCollection<Elements, ElementOfResult> : some Collection<.Element == ElementOfResult> = LazyMapSequence< LazyFilterSequence< LazyMapSequence<Elements, ElementOfResult?> >, ElementOfResult > extension LazyMapCollection { public func compactMap<U>(_ transform: @escaping (Element) -> U?) -> LazyCompactMapCollection<Base, U> { // ... } public func filter(_ isIncluded: @escaping (Element) -> Bool) -> LazyCompactMapCollection<Base, Element> { // ... } }
2:19 AM
opaque return typeだけど、実際の型は2つの関数で同じだよって事を表明できるのか。
Avatar
↓は OK なのに protocol P {} func foo<T: P>() -> T { fatalError() } ↓はダメなのか。 protocol P {} func foo() -> some P { fatalError() }
2:21 AM
A function with an opaque result type is also required to have a return statement even if it does not terminate:
func f9() -> some P { fatalError("not implemented") // error: no return statement to get opaque type }
(edited)
2:22 AM
代入先から
2:22 AM
推論できるからか。
2:22 AM
あー、頭がバグってた・・・
2:22 AM
関係ない話だった。
Avatar
omochimetaru 3/6/2019 2:22 AM
NeverP[f9] みたいなものを内部的に生成してくれたらそこは無理やり通すようにできそうな気もする
2:23 AM
some P に対してとりあえず真の型が確定しないからエラーっていうのはひとまずはわかりやすいけど。
Avatar
えっと、同じ話にするにはどうすればいいかな・・・
Avatar
↓の someP がありってことは変数でも some が使える??それともトップレベルの変数は変数じゃなくてプロパティ扱いなのかな?アクセス修飾子も付けられるし。 // Module A public protocol P { mutating func flip() } private struct Witness: P { mutating func flip() { ... } } public var someP: some P = Witness() // Module B import A someP.flip() // ok: flip is a mutating function called on a variable (edited)
Avatar
omochimetaru 3/6/2019 2:46 AM
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: let strings: some Collection = ["hello", "world"] (edited)
2:46 AM
letとかvarには書けるみたいですね。
2:47 AM
>「変数じゃなくてプロパティ」 プロパティではない変数というのはどういう意味ですか?
Avatar
↓の a はプロパティじゃないよね? func foo() { var a: Int = 42 a += 1 print(a) }
Avatar
omochimetaru 3/6/2019 2:49 AM
一応 stored property なのかと思ってた。computed propertyにできるから。 func f() { var a: Int { return 3 + 3 } print(a) }
Avatar
うん、今↓を試してた。 func foo() { var a: Int { return Int.random(in: 1...10) } print(a) }
Avatar
omochimetaru 3/6/2019 2:50 AM
get とか didSet とかも書けたはず (edited)
2:51 AM
@swift-main func foo() -> __opaque Collection { return [1, 2] } (edited)
Avatar
swiftNightly BOT 3/6/2019 2:51 AM
exit status: 1 with stderr:<stdin>:1:23: error: consecutive statements on a line must be separated by ';' func foo() -> __opaque Collection { ^ ; <stdin>:1:15: error: use of undeclared type '__opaque' func foo() -> __opaque Collection { ^~~~~~~~ <stdin>:1:24: error: 'Collection' cannot be constructed because it has no accessible initializers func foo() -> __opaque Collection { ^ <stdin>:1:24: error: protocol 'Collection' can only be used as a generic constraint because it has Self or associated type requirements func foo() -> __opaque Collection { ^ (edited)
Avatar
まだマージされてないのでは?
2:52 AM
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...
2:52 AM
というか
2:52 AM
まだレビュー中だし。
Avatar
omochimetaru 3/6/2019 2:52 AM
実装は結構進んでるんですよ
2:52 AM
masterには全く入れずにずっとやってるのか。
Avatar
master に入るのはレビュー通った後じゃないのかな?
Avatar
omochimetaru 3/6/2019 2:53 AM
特定ブランチのbotが欲しい・・・
Avatar
ブランチの数だけビルドしてボット化するのつらそう・・・
Avatar
omochimetaru 3/6/2019 2:54 AM
仮実装がmasterに入ってることはまあまあありますよ
2:54 AM
@swift-main func f(a: __shared Int) {}
Avatar
swiftNightly BOT 3/6/2019 2:54 AM
no output
Avatar
omochimetaru 3/6/2019 2:54 AM
これとか。
Avatar
まったく当てにならないけど、 The Swift Programming Language には
Properties associate values with a particular class, structure, or enumeration.
とは書かれてる。 Swift におけるプロパティの定義がわからないなぁ・・・。広義にはすべての変数や定数はプロパティなのかな?
2:59 AM
=== ↓の S はどこから来たの?? protocol GameObject { associatedtype ObjectShape: Shape var shape: ObjectShape } struct Player: GameObject { var shape: some Shape { ... } /* infers typealias Shape = opaque result type of Player.shape */ } let sv: S.SomeType // ok: names the opaque result type of S.someValue() sv = S().someValue() // ok: returns the same opaque result type https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md#associated-type-inference (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 3/6/2019 3:04 AM
protocol P { associatedtype SomeType func someValue() -> SomeType } struct S : P { func someValue() -> opaque SomeType { ... } } let sv: S.SomeType sv = S().someValue()
3:04 AM
直前の説明文から推測すると、こういう事じゃないですか? (edited)
Avatar
GameObjectPlayer はどこいったんだろう??後半だけコードを修正し忘れたのかな?
3:09 AM
let shape: Player.ObjectShape shape = Player().shape (edited)
Avatar
omochimetaru 3/6/2019 3:10 AM
Playerのところは
/* infers typealias Shape = opaque result type of Player.shape */
↑これが言いたいことだと思います
Avatar
うーん、↑のコードが言いたかったんじゃないかな?
Avatar
omochimetaru 3/6/2019 3:11 AM
あれ?これはでもよくわからないな
Avatar
↓の let result: Int = f7(-i) は禁止だけど func f7(_ i: Int) -> some P { if i == 0 { return f7(1) // ok: returning our own opaque result type } else if i < 0 { let result: Int = f7(-i) // error: opaque result type of f7() is not convertible to Int return result } else { return 0 // ok: grounds the recursion with a concrete type } }
3:12 AM
ちょっと違うか
3:13 AM
でも、 Player.ObjectShapesome Shape を入れようとしてもこのケースではエラーにならないよってことでは?
Avatar
omochimetaru 3/6/2019 3:13 AM
それはIntで受けてるのがだめだよって話と、自己再帰は正しく推論するよって話ですかね
Avatar
Player.ObjectShape に some Shape を入れようとしても
というか、逆で、 Player.ObjectShapePlayer().shape で返される some Shape だと推論されるよってことかな。
(edited)
Avatar
omochimetaru 3/6/2019 3:15 AM
Player.shapeのsome Shapeが、Player.ObjectShapeになる
3:15 AM
protocolのassociated typeを、conformanceを満たすのに使ったfuncやvarのsome typeで充足できるって
3:15 AM
話っぽいですね
3:15 AM
2箇所で使われてたら、真の型の同一性がチェックされるのか?
Avatar
↓この話おもしろい。
Hamish provides a complete explanation on StackOverflow as to why an existential of type P does not conform to the protocol P. The following example from that answer demonstrates the point with an initializer requirement:
protocol P { init() } struct S: P {} struct S1: P {} extension Array where Element: P { mutating func appendNew() { // If Element is P, we cannot possibly construct a new instance of it, as you cannot // construct an instance of a protocol. append(Element()) } } var arr: [P] = [S(), S1()] // error: Using 'P' as a concrete type conforming to protocol 'P' is not supported arr.appendNew()
(edited)
Avatar
norio_nomura 3/6/2019 3:30 AM
特定ブランチのbotが欲しい・・・ macOS版のtoolchainは随時更新されてるけど、Linux版は無いですね。あればローカル実行して随時ボットを動かすことはそれ程難しくなさそうですが… https://github.com/apple/swift/pull/21137#issuecomment-468118328
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...
Avatar
omochimetaru 3/6/2019 3:32 AM
そうか、普通のやつはビルド済みのパッケージがあるけど、ブランチだと無いのか。
Avatar
↓なので、 func makeOpaque<T>(_: T.Type) -> some Any { /* ... */ } var x = makeOpaque(Int.self) x = makeOpaque(Double.self) // error: "opaque" type from makeOpaque<Double> is distinct from makeOpaque<Int> やっぱり↓で正しそう。 func foo1() -> some Foo { return Foo1() } func foo2() -> some Foo { return Foo2() } var foo = foo1() foo = foo2() // コンパイルエラー
3:35 AM
これってモジュール(というかビルド単位)をまたいだときにどうやって静的に判定するの? ABI に影響なくできる?
3:37 AM
Opaque result types are an ABI-additive feature
3:37 AM
書いてあった。
3:37 AM
additive だからいいのか。
3:44 AM
↓は OK ?エラー? func p1() -> some P { return S(1) } func p2() -> some P { return S(2) } var s = p1() s = p2() // OK ?エラー? (edited)
Avatar
norio_nomura 3/6/2019 3:57 AM
swift-PR-21137-216ツールチェインではエラーになった。 $ pbpaste protocol P {} struct S: P { let int: Int init(_ int: Int) { self.int = int } } func p1() -> __opaque P { return S(1) } func p2() -> __opaque P { return S(2) } var s = p1() s = p2() // OK ?エラー? $ pbpaste|xcrun --toolchain org.swift.pr.21137.216 swiftc - <stdin>:17:5: error: cannot assign value of type '(__opaque main.(file).p2()@<stdin>:13:6)' to type '(__opaque main.(file).p1()@<stdin>:10:6)' s = p2() // OK ?エラー?% swiftcの出力に変更 (edited)
Avatar
ということは、静的に実の型を解析してるわけじゃなくて、 some P の宣言単位(?)でチェックされてるってことですね。
Avatar
omochimetaru 3/6/2019 4:11 AM
実際に真の型が同一でも駄目と
Avatar
↓は OK という理解。 protocol P {} protocol Q { associatedtype T: P func foo1() -> T func foo2() -> T } extension Int: P {} struct S: Q { func foo1() -> some P { return 1 } func foo2() -> some P { return 2 } } let s = S() var a = s.foo1() a = s.foo2() // OK
4:15 AM
この opaque result type の概念、素晴らしいと思うけどコードの見た目が微妙そう。 var a: some Foo = ... let b: some Foo = ... a = b // コンパイルエラー ab が同じ型に見えるのに。
4:15 AM
いや、だからこその some なのか。
4:16 AM
some Foosome Foo だと英語的に同じじゃないという意味になるのか。
Avatar
omochimetaru 3/6/2019 10:20 AM
>The opaque type must be the entire return type of the function, For example, one cannot return an optional opaque result type: func f(flip: Bool) -> (some P)? { // error: `some P` is not the entire return type ... }
10:20 AM
The grammatical production for opaque result types is straightforward: type ::= opaque-type opaque-type ::= 'some' type The type following the 'some' keyword is semantically restricted to be a class or existential type, meaning it must consist only of Any, AnyObject, protocols, or base classes, possibly composed using &.
10:21 AM
() -> some (P?)() -> (some P)? も使えなくて困らないんだろうか?
10:21 AM
throwsとOptionalで格差が出ちゃうのも気持ち悪い
10:22 AM
Collection.firstとか使えないと思ったが、.first.first: Element? だから、ここは some のユースケースじゃないので大丈夫なんだけど・・・。
Avatar
でもそれができると existential になっちゃうし、同様に [some P] とかも認めないといけないんじゃないかな?
Avatar
omochimetaru 3/6/2019 10:31 AM
existentialになるってどういうことですか? あと、返り値じゃなければ[some P]はアリ
10:31 AM
var cc = [c] cc.append(c) // ok: cc's Element == the result type of makeMeACollection
10:31 AM
↑この例のところです
Avatar
ほんとだ。型は決まってるわけだから別にexistentialじゃなくてできるか。
Avatar
omochimetaru 3/6/2019 11:36 AM
はい
Avatar
たしかにそれができるのにreturnできなくて困るケースないのかな…。
Avatar
(some P)?[some P]return できてダメな理由ってなんだろう?
Avatar
omochimetaru 3/6/2019 12:33 PM
わからない
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 3/6/2019 2:09 PM
Pitchの方のフォーラムスレッドでは言及があるかもしれないですね
Avatar
omochimetaru 3/7/2019 1:38 AM
Optional<some P>が使えないのは不便じゃね、後回しなだけ?本質的な問題があるのか? って Tony Allevato が10時間前に質問してて
1:38 AM
ジョーグロフ「This is not a fundamental limitation. It could be added later. I'll include this in the "future directions".」
1:39 AM
なので、本質的な問題はないっぽい。よかった。
Avatar
なるほど。
1:48 AM
Future Direction に書かれてる "where constraints on associated types of opaque types" とか "Conditional conformances" とかがないと標準ライブラリの問題に適用できなさそうなんだけど、それなしにでも先に導入したい理由があるのかな?
Avatar
omochimetaru 3/7/2019 1:55 AM
cocoaphonyさんが「mapで使えないよね?」って聞いてて
1:56 AM
Joe Groffが回答してるんだけど英語がよくわからん。 「Granted, this initial revision of opaque result types doesn't either, but it could get there in time.」
1:56 AM
この辺の会話。
1:56 AM
今駄目だけど後々やると思う って感じかな
1:58 AM
標準ライブラリの問題に適用できなさそう
全滅ではなくて、使えるところもある でも互換性とかどうなるんだ
1:59 AM
func foo() -> some Collection where _.Element == Int { ... }
2:00 AM
この書き方だと、someについてるwhereとfuncについてるwhereのぶら下がりが曖昧だから
2:00 AM
Swift's notation for generic constraints generally requires naming the things being constrained; you say that a particular generic parameter conforms to a protocol by naming the generic parameter and the protocol it conforms to, like , and you put further constraints on its a...
2:01 AM
T: Protocol<.Type == Int> こっちの記法の話と並行して進めたいのかな
Avatar
そういう意味合いもあるのか。
2:24 AM
where でだらだら続くのは視認性も悪いし P<.T == Foo> 形式の方がいいよね。
Avatar
omochimetaru 3/7/2019 4:58 AM
>JoeGroff: The implementation for an opaque type in another module does use witness tables just like a generic parameter; it has to in order to accommodate protocol resilience.
4:59 AM
モジュールまたいでopaque typeを使うときはジェネリックパラメータのところで使うwitness tableを使う
5:00 AM
もうランタイムレベルではassociated type付きexistentialが存在してると言って良さそう
5:00 AM
あ、 struct Box<T: P> { var value: T } の形でそれは元からあったか。
5:02 AM
IRGenのレベルで見た時にこの機能がこれまでと違うのはモジュール内部で使う直接形式と外部で使うresilentな形式が同時に生成されることか。関数シンボルが2つできるのかな? (edited)
Avatar
omochimetaru 3/7/2019 5:42 AM
Protocol制約記法のスレのほうで
5:43 AM
Generalized Existentialの記法も同時に扱われているが
5:43 AM
Existential var x: Protocol<.A == Int, .B: P>
5:43 AM
この路線だと、普通のPと同じになるのがいいね
5:43 AM
let xs: Collection<.Element == Int> = [1,2,3]
5:45 AM
var x: Any<Protocol where _.A == Int, _.B: P> ←こっちだと既存のExistentialとの整合性問題がある
Avatar
omochimetaru 3/7/2019 7:37 AM
protocol Z<T> { associatedtype R ... } func baz(_ z: Z<Int, .R == Int>) { ... }
7:38 AM
もし、Parameterized Protocolが導入された未来において、< >の記法が、ジェネリックパラメータとassoctypeの両方をまとめて書く事になっちゃうけど、ギリ衝突はしない
Avatar
めっちゃおもろい
4:37 PM
出来なかったことに色々手が届きそう
Avatar
omochimetaru 3/8/2019 1:04 AM
Swift5世代で結構ジェネリクス周りが進むかもね
Avatar
omochimetaru 3/8/2019 1:47 AM
ここ2年ぐらい、「なんにせよそれはABI安定化してからやな」って流れた話題がそこそこあった気がするし
Avatar
いい話だ
Avatar
omochimetaru 3/8/2019 3:22 AM
When the first seed of Swift came out many years ago, there were technical reasons for the "self or associated type" constraint on protocol existentials: At that time, protocol witness tables did not carry associated type information, so it was impossible to re-open the dynam...
3:23 AM
Generalized Existential?スレはここか。
3:28 AM
Selfかassoctypeのあるprotocolをexistentialに使えない理由として、 昔は実装上witness tableに真の型が入ってなくてre-openできなかったから無理だったけど、 最近Recursive constrained protocolの対応をしたときに、それも実行時に運ぶようになったから、 原理上可能になっている その後のくだりがよくわからなくって、 Selfとassoctypeに関してcontravariantなメソッドをextentionで追加できるという型システム上の問題はすでに存在している とかなんとか
3:31 AM
associated typeについてconstraintを設定できないから完全なgeneralized existentialの話ではないらしい
Avatar
ふむ
3:37 AM
型システム上の問題
tsのisEqual的なアレかな
(edited)
Avatar
omochimetaru 3/8/2019 3:38 AM
AnyEquatableを作ろうとすると Int と Stringの比較が静的には許可されて実行時になる話と関係してそう。 (edited)
3:38 AM
We'd follow the existing rule which is that protocol members that use contravariant Self or associated types aren't available on the existential
3:38 AM
そもそもこれなんだっけ
3:39 AM
あ、これは普通の existential 作れない事を言ってるのか
3:39 AM
(contravariant Self) or (associated types) か
Avatar
最後の文脈はそれっぽい
Avatar
omochimetaru 3/8/2019 3:39 AM
なんでSelfの話するときにcontravariantってついてるのかよくわからない。
Avatar
引数Self限定なんすよ
3:40 AM
返り値Selfはオッケー
Avatar
omochimetaru 3/8/2019 3:40 AM
あ〜〜〜
Avatar
この間わいわいでやった
Avatar
omochimetaru 3/8/2019 3:40 AM
そういう意味か、「Selfが出現してたらexistentialが作れない」ではないのか。
3:41 AM
protocol P { func a() -> Self } struct S : P { func a() -> S { fatalError() } } func main() { var p: P = S() }
3:41 AM
ほんとだ。
Avatar
言ってしまえばinit制約だってある種のSelfだべな
Avatar
omochimetaru 3/8/2019 3:41 AM
Selfであってもcontravariant positionになっていないならば許すのね。
3:42 AM
initはSelfを返してるようなもんだから、covariantだから、セーフかね
3:43 AM
protocol P { init(name: String) func a() -> Self } struct S : P { init(name: String) {} func a() -> S { fatalError() } } func takeExistentialArg(_ p: P) {}
3:43 AM
なるほどね
3:44 AM
protocol P { init(name: String) func a() -> Self } protocol Q { func takeSelf(_ self_: Self) } func takeExistentialArgP(_ p: P) {} // Protocol 'Q' can only be used as a generic constraint because it has Self or associated type requirements func takeExistentialArgQ(_ q: Q) {}
3:44 AM
このエラーメッセージ、「it has Self」のところ、「it has contravariant Self」のほうが、良さそう。
3:46 AM
protocol P { init(name: String) func a() -> Self } protocol Q { func takeSelf(_ self_: Self) } extension P { func takeSelf(_ self_: Self) { } } func takeExistentialArgP(_ p: P) {}
3:46 AM
However, nowadays we also have protocol extensions, so even if a protocol doesn't have any core requirements with contravariant Self or associated type arguments, contravariant protocol methods can be added by extensions, so the type system issues unavoidably exist already.
3:47 AM
たとえ、protocol Pの本体が、contravariant Selfを使っていないとしても、extensionでそれを追加する事ができちゃうので、すでに一部壊れてる
3:50 AM
extension P { func transfer(_ self_: Self) -> Self { return self_ } } func takeExistentialArgP(_ p: P) { // Member 'transfer' cannot be used on value of protocol type 'P'; use a generic constraint instead let a = p.transfer(p) }
3:50 AM
ウオオ
3:51 AM
protocol Pに生やしたのに existential Pでは使用禁止になるケースあるのか。
3:53 AM
これがまさに
We'd follow the existing rule which is that protocol members that use contravariant Self or associated types aren't available on the existential.
3:54 AM
だから、contra Self or assoctypeなメンバーの使用はできないという制限(これは実は既存)のもとで contra Self or assoctypeな protocolでもexistentialを可能にしよう っていう提案か。 (edited)
3:56 AM
これって要するに、
3:56 AM
protocolからcontra Selfとassoctypeを取り除いた親protocolを作って、親protocolのexistentialを使う、っていう現時点で可能なワークアラウンドと、表現能力は一緒かな (edited)
3:59 AM
existential P が protocol P に準拠できないのもこの差分があるから、って言うこともできるんかな
4:00 AM
つまり、existential Pは <T: P> と違って真の型を失ったただの型境界にすぎない?
4:03 AM
func foo<T: P>(_: T) extension P { func _forwardToFoo() { foo(self) } } func callFooOnEach(_ ps: [P]) { for p in ps { p._forwardToFoo() } }
4:04 AM
you can in fact "open" the existential by invoking a protocol extension method, which will give you Self as the dynamic type of the value inside the method, which you can then pass to generic functions:
4:04 AM
protocol extension経由でSelfをreopenできるってこれなんか前話したな
4:05 AM
Pの中に隠れてるから _forwardToFoo を呼ぶ側からみるとセーフなのか。
5:25 AM
existential PがPにconformしないのって結局どこがネックなんでしたっけ
Avatar
おもちのは前あった裏技ですね。そろそろprotocolとexistential周りの裏技一覧が欲しい
Avatar
omochimetaru 3/8/2019 5:35 AM
なんかわかってきた気がする
5:41 AM
extensionでPにSelfを引数にとるメソッドを追加できるから、 existential Pが、もしPに準拠してたら、そのメソッドは、existential Pを受け取ることになるけど、 exPはすべてのT:Pのスーパータイプだから、実際の型はSだったりして、SにおいてはそのメソッドはSを受け取るはずだから、壊れて困る
5:43 AM
exPはT:Pの共通の親である って性質と、 exP自身がPである、って性質は、一般には両立しないのでは
Avatar
Exsistentialに対して直接呼ぶのはコンパイルエラーにできるけど、T: P越しだと弾けないのか
Avatar
omochimetaru 3/8/2019 5:44 AM
self reopenの技をErrorに対して使えば、クラッシュさせられるのかな?
Avatar
あ。。
Avatar
omochimetaru 3/8/2019 5:48 AM
extensionで追加したメソッドでSelfを引数に受けたとしても、その先の処理でextensionの中で何をすると問題が起こせるか、思いつかない・・・
Avatar
mutating func killme(_ new:Self) { self = new } (edited)
5:49 AM
これ?
Avatar
omochimetaru 3/8/2019 5:50 AM
お!
Avatar
壊すのは 得意だよ
Avatar
omochimetaru 3/8/2019 5:50 AM
www
Avatar
試してみたんですけど、これだと引数の型がexistential PじゃなくてT: Pになりませんか?
Avatar
omochimetaru 3/8/2019 6:03 AM
コードで見たい
Avatar
omochimetaru 3/8/2019 6:32 AM
@swift-5.0.3 struct IntError : Error { var value: Int } struct StringError : Error { var value: String } extension Error { mutating func assign(other: Self) { self = other } } func dispatchAssign<E: Error>(_ a: inout E, _ b: E) { a.assign(other: b) } func main() { let e0 = IntError(value: 3) var e0e: Error = e0 dump(e0e) let e1 = StringError(value: "a") let e1e: Error = e1 dispatchAssign(&e0e, e1e) dump(e0e) } main()
Avatar
swift50 BOT 3/8/2019 6:32 AM
▿ main.IntError - value: 3 ▿ main.StringError - value: "a"
Avatar
omochimetaru 3/8/2019 6:33 AM
別の型になって生き延びとる
Avatar
omochimetaru 3/8/2019 6:45 AM
ex.Error に対する mutating funcを呼び出すためには、一度 ex.Error型の変数に代入する必要があるから、ex.Errorから元のIntErrorに書き戻す事が無いので、大丈夫
Avatar
mutating funcはExsistentialじゃないとダメなのか
Avatar
omochimetaru 3/8/2019 6:49 AM
@swift-5.0.3 struct IntError : Error { var value: Int } struct StringError : Error { var value: String } extension Error { mutating func assign(other: Self) { print("assign:") print("self type=", type(of: self)) print("other type=", type(of: other)) print("dump self") dump(self) print("dump other") dump(other) switch self { case is IntError: print("self is IntError") case is StringError: print("self is StringError") default: break } print("---") self = other } } func dispatchAssign<E: Error>(_ a: inout E, _ b: E) { a.assign(other: b) } func main() { let e0 = IntError(value: 3) var e0e: Error = e0 dump(e0e) let e1 = StringError(value: "a") let e1e: Error = e1 dispatchAssign(&e0e, e1e) dump(e0e) } main()
Avatar
swift50 BOT 3/8/2019 6:49 AM
▿ main.IntError - value: 3 assign: self type= Error other type= Error dump self ▿ main.IntError - value: 3 dump other ▿ main.StringError - value: "a" self is IntError --- ▿ main.StringError - value: "a"
Avatar
omochimetaru 3/8/2019 6:49 AM
type(of: self) だと ex.Error に見えるけど is で調べると元の型に見えるね
6:52 AM
Why doesn't this Swift code compile? protocol P { } struct S: P { } let arr:[P] = [ S() ] extension Array where Element : P { func test<T>() -> [T] { return [] } } let ...
6:52 AM
もし、Swift.Errorに init() が生えてたら
6:52 AM
ここのHamishさんのappendNew()のパターンで
6:52 AM
壊れそうな気がするんだけど。
Avatar
昨日それ読んでたんですけど、逆にinit()が生えてなければself conformしていても問題なさそうに思えるんですよね
Avatar
omochimetaru 3/8/2019 6:54 AM
うむ。さっき思ったんだけど、
6:55 AM
Protocolの全ての機能 { contravariance Self associatedtype Existentialを作れる範囲の機能{ extension contravariant Self Existentialに対して呼び出せる機能 { covariance Self (init, static func) ExistentialがSelf conformできる範囲の機能{ func requirement } } } } (edited)
6:55 AM
こういうことかなあと
6:59 AM
で、そのスレッドで提案しているのは、これを
6:59 AM
Protocolの全ての機能 { Existentialを作れる範囲の機能{ contravariance Self associatedtype extension contravariant Self Existentialに対して呼び出せる機能 { covariance Self (init, static func) ExistentialがSelf conformできる範囲の機能{ func requirement } } } }
6:59 AM
こう変更しようってことかなと
Avatar
omochimetaru 3/8/2019 7:08 AM
struct IntError : Error { var value: Int } func mutateError(_ e: inout Error) {} struct Cat { var error: IntError } func main() { var cat = Cat(error: IntError(value: 3)) // Cannot pass immutable value as inout argument: implicit conversion from 'IntError' to 'Error' requires a temporary mutateError(&cat.error) }
7:12 AM
existentialへの変換はアップキャストみたいな扱いで、戻してくるところはダウンキャストみたいに非安全としてガードされる
7:16 AM
import Foundation @objc protocol P { } func genericP<T: P>(_ t: T) {} func existentialP(_ p: P) { genericP(p) }
7:16 AM
Yes, there’s already logic to detect and diagnose this case in fact (@objc protocols are self-conforming, except when they contain static members or initializers).
7:16 AM
Yes, there’s already logic to detect and diagnose this case in fact (@objc protocols are self-conforming, except when they contain static members or initializers). Slava ···On Jan 18, 2017, at 12:10 AM, Anton Zhilin via swift-evolution wrote: There is also a caveat w...
7:16 AM
@objc protocol は self-conformance していて、その条件チェックもされてるって!
7:17 AM
import Foundation @objc protocol P { init() } func genericP<T: P>(_ t: T) {} func existentialP(_ p: P) { // Cannot invoke 'genericP' with an argument list of type '(P)' genericP(p) } pにinitつけたらエラーになった。
Avatar
@objcのSelf conformingは知ってた
7:33 AM
でも確かぶっ壊れがあって
Avatar
omochimetaru 3/8/2019 7:33 AM
それが定義ベースで検査されてる
7:33 AM
昨日それ読んでたんですけど、逆にinit()が生えてなければself conformしていても問題なさそうに思えるんですよね
↑これが実現されてるってこと
Avatar
ObjcProtocol.selfがObjcProtocolにキャストできる抜け穴がある
Avatar
omochimetaru 3/8/2019 7:33 AM
えw
Avatar
治ったかは知らない、確かめてない
7:34 AM
RxSwiftのパッチ作ってる時に気づかずに踏んでざは先生にごめんなさいした
Avatar
omochimetaru 3/8/2019 7:35 AM
import Foundation @objc protocol P {} func takeGeneric<T: P>(_ t: T) {} func main() { let pMeta = P.self // Argument type 'P.Protocol' does not conform to expected type 'P' takeGeneric(pMeta) }
7:35 AM
大丈夫そう
Avatar
確か、@objc protocolをassociatedtypeに突っ込んだ上でそれをやると崩壊した
Avatar
Xcode10.1だとまだ壊れてますね
11:35 AM
import Foundation protocol Animal { associatedtype Food } protocol Carnivore: class { func bark() } class Lion: Carnivore, Animal { typealias Food = Carnivore func bark() { print("gawgaw") } } func something<T: Animal>(_ type: T.Type) { print(T.self as? T.Food) }
Avatar
ジェネリック引数と opaque result type の関係について考えてたんですが、その二つは双対の関係になってませんか?つまり、 func useFoo<F: Foo>(_ foo: F) { /* ... */ } func makeFoo() -> some Foo { /* ... */ } があったとして、
  • useFoo の利用者は Foo の具体的な型を決定し、実装者はある Foo についてコードを記述する。
  • makeFoo の実装者は Foo の具体的な型を決定し、利用者はある Foo についてコードを記述する。
という関係があるということです。どちらも、( specialize されれば)具体的な型で記述されたのと同等のパフォーマンスを実現できるという点、具象型と抽象型を橋渡しするものである点で共通です。
Avatar
そうすると、ジェネリクスにおいて「ある Foo 」を利用する人が「ある Foo 」に仮の名前(型パラメータ)を与えるのと同じように、 opaque result type についても「ある Foo 」を利用する人、つまり some Fooreturn する関数を利用する人が仮の名前を与えるような構文もあり得る気がします。そうすれば、字面上同じ some Foo 同士で代入できない↓のようなコードにならずに、それぞれの some Foo に利用者側が別の名前を割り当てて使うことができるかもしれません。 var a: some Foo = foo1() let b: some Foo = foo2() a = b // `some Foo` 同士の代入だけどコンパイルエラー (edited)
3:36 PM
たとえば↓のようなイメージ。 func foo1() -> some Foo { /* ... */ } func foo2() -> some Foo { /* ... */ } var a: Bar = foo1<Bar>() // `some Foo` に `Bar` の名前を付ける let b: Baz = foo2<Baz>() // `some Foo` に `Baz` の名前を付ける a = b // `Baz` を `Bar` に代入しようとしているのでコンパイルエラー ただし、 foo1 の戻り値同士は代入可能なので、 foo1 の呼び出し箇所間で同じ名前を与えるためにどういう構文が良いのかわかりません。 (edited)
Avatar
ジェネリック引数とsome返り値が対であると言う考え方は結構しっくりきますね
3:39 PM
ジェネリック返り値は大体まるで使い物にならないので
3:39 PM
まさに欲しかったものな気がしています
Avatar
ですね。初めて見たときからジェネリクスに似てる気がするもののそれをうまく言語化できずにいたんですが、↑のような対として考えてしっくり来ました。
3:55 PM
利用時に名前を付けるうんぬんは対として考えたときの可能性の話で、 some Foo でも( some のニュアンスで some Foo 同士が異なる型として解釈できるので)十分だとは思います。
Avatar
norio_nomura 3/8/2019 11:27 PM
なるほど。 func useFoo(_ foo: some Foo) { /* ... */ } func makeFoo() -> some Foo { /* ... */ } https://forums.swift.org/t/se-0244-opaque-result-types/21252/59
You're correct that they're duals. I touched on this briefly in "future directions". It would be great to eventually support some Foo as an argument type as well, which would let you write: func useFoo(_ foo: some Foo) { /* ... / } func makeFoo() -> some Foo { / ... */ } ...
👍 1
Avatar
GeneralizedExistentialと、HigherKindedTypeがそれぞれ無いことによって表現できないプログラムを上手く補完できるように感じてるけどあってるかな
3:46 AM
Collection.mapの結果は一時的な利用であればCollectionでさえあればよくって、中身の実装がArrayなのかLazyなのかは、mapの結果を得たときにプログラマが知る必要はなく、ランタイム時と最終的に確定した型に押し込めるタイミングで一意でさえあればいい、はず。
Avatar
higher kinded typeでやりたいのって functor みたいな制約を書いたり、 functor に対して抽象的に map を使ったコードが書けたりってことじゃないですか? some P はプロコトルの制約として使えないから難しそうな気が。
Avatar
むむ
7:57 AM
Opaque result types cannot be used in the requirements of a protocol:
本当だ
7:57 AM
じゃあHigherKindedが無いのは無いままですね
😢 1
Avatar
↓がもし通るならややこしそう。 protocol P { associatedtype F: Foo func foos() -> (F, F) } protocol Q { associatedtype F: Foo associatedtype G: Foo func foos() -> (F, G) } struct S: P { // これはエラーになる? func foos() -> (some Foo, some Foo) { /* ... */ } } struct T: Q { func foos() -> (some Foo, some Foo) { /* ... */ } } (edited)
Avatar
norio_nomura 3/10/2019 2:17 AM
someFooはtypoかな?
🙏 1
Avatar
typo です。 iPhone から打ってて気づいてませんでした。直しました。
3:12 AM
↓が OK だと思われるので、↑の S も OK でないと変な気もする。 protocol P { associatedtype F: Foo func foo1() -> F func foo2() -> F } struct S { // これは多分 OK func foo1() -> some Foo { /* ... */ } func foo2() -> some Foo { /* ... */ } } let s = S() var a: some Foo = s.foo1() let b: some Foo = s.foo2() a = b // これも多分 OK
Avatar
protocol P { associatedtype Dep func a(arg: Dep) init() init(with dep: Dep) } extension P { init(with dep: Dep) { self = Self.init() } } class A: P { required init() {} func a(arg: @autoclosure () -> Int) {} } _ = A(with: 1) ↑のコードがSwift 5からエラーになるのってSR-5719で@autoclosureが型じゃなくなったからって理解であってますか。 (edited)
Avatar
initに@autoclosure渡せないし、素直にclosureで書くようにするしかないか。
Avatar
norio_nomura 3/11/2019 2:42 PM
変更を見ると
  • Move @autoclosure flag from function type to parameter declaration
って書かれてるから、その理解で合ってそうですね。 https://github.com/apple/swift/pull/20152
These changes aim to: Move @autoclosure flag from function type to parameter declaration Serialize @autoclosure as part of the parameter declaration Convert it from being a type attribute to be d...
Avatar
普通クロージャをconformしてautoclosureをオーバーロードじゃダメですかね?
Avatar
オーバーロードするのはinit(with:)?
Avatar
omochimetaru 3/12/2019 1:43 AM
@swift-5.0.3 protocol P { associatedtype Dep func a(arg: () -> Dep) init() init(with dep: Dep) } extension P { init(with dep: Dep) { self = Self.init() } } class A: P { required init() {} func a(arg: @autoclosure () -> Int) {} } _ = A(with: 1)
Avatar
no output
Avatar
omochimetaru 3/12/2019 1:44 AM
これで通りますね
Avatar
protocol側を変えるのか。ただそれだとinitに渡す時にはautoclosureされないから渡したやつの初期化処理入ってしまうってことですよね。 (edited)
Avatar
initオーバーロードです。普通クロージャ版でprotocolにconformして、利用者用のextensionとしてconveniences initでautoclosureを使います
Avatar
protocol P { associatedtype Dep func a(arg: Dep) init() init(with dep: Dep) } extension P { init(with dep: Dep) { self = Self.init() } } final class A: P { required init() {} func a(arg: () -> Int) {} convenience init(with dep: @escaping @autoclosure () -> Int) { self.init(with: dep) } } _ = A(with: 1) finalくっつける必要あったけど、これでいけた。
3:03 AM
ありがとう、この方向でいってみようと思います!
Avatar
enum Foo { case a, b } ってenumがあるとしてこれのArrayをリテラルで作る際に変数つっこむ時は let a: [Foo] = [.a, .b] って書いてて、引数貰う側の型指定で明示されてないところに変数にせずにリテラルつっこむ時にはしょうがなく [Foo.a, Foo.b] って書いてたんですけど [Foo.a, .b] みたいに後続のものは省略できたんですねっていうのを今気づきました。 (edited)
Avatar
omochimetaru 3/13/2019 7:35 AM
@swift-5.0.3 enum Foo { case a, b } let xs = [.a, Foo.b, .a]
Avatar
no output
Avatar
omochimetaru 3/13/2019 7:35 AM
途中でもいいんですね。
Avatar
omochimetaru 3/15/2019 4:09 AM
class Animal {} class Cat : Animal {} class User { var cat: Cat init(cat: Cat) { self.cat = cat } static let keyPaths: [KeyPath<User, Animal>] = [ // Key path value type 'Cat' cannot be converted to contextual type 'Animal' \User.cat ] }
4:10 AM
KeyPath型はReadonlyなのでcovarianceとして正しそうだけど、これはできないのか。
Avatar
Kishikawa Katsumi 3/16/2019 6:04 AM
https://github.com/apple/swift-log こんなプロジェクト始まってたんですね。Swiftにおける標準ロギングパッケージ
Contribute to apple/swift-log development by creating an account on GitHub.
Avatar
omochimetaru 3/16/2019 6:05 AM
知らなかった
Avatar
Proposal Review: SSWG-0001 (Server Logging API) After the great discussion thread, we are proposing this as a final revision of this proposal and enter the proposal review phase which will run until the 20th January 2019. We have integrated most of the feedback from the disc...
Avatar
omochimetaru 3/18/2019 2:37 AM
This prepares swift-package-manager to adopt more functionality in Foundation. The implementation in swift-package-manager is EXTREMELY unfriendly to porting due to the highly POSIX/UNIX specific ...
2:38 AM
compnerdさんがSwiftPMをWindows対応するために動き出した気配がする
2:38 AM
SwiftPM.FileSystem.getDirectoryContentsをFoundationで実装するようにしたりなどのパッチなんだけど、 逆にlibCブリッジで書いてた事が驚き (edited)
2:39 AM
SwiftPM初期にFoundationが不完全だった、みたいな時系列の都合があったのかな (edited)
Avatar
norio_nomura 3/18/2019 4:54 AM
The Package Manager for the Swift Programming Language - apple/swift-package-manager
The Foundation Project, providing core utilities, internationalization, and OS independence - apple/swift-corelibs-foundation
4:57 AM
最初からLinuxで動かすことを想定していたみたいだから、これから作っていこうとしていたswift-corelibs-foundationに依存するのを避けるのは理解できる。
Avatar
omochimetaru 3/18/2019 7:18 AM
なるほど 最初のコミットの時期もかなり近いですね
Avatar
omochimetaru 3/19/2019 3:48 AM
Hi all, @dan-zheng and I wrote a proposal to introduce static callables to Swift. This proposal is also available as a gist here. We'd love to hear your feedback. Introduce callables Proposal: SE-NNNN Authors: Richard Wei, Dan Zheng Review Manager: TBD Status: Implementati...
3:49 AM
おもしろそうな話題
3:49 AM
struct Adder { var base: Int call(_ x: Int) -> Int { return base + x } } let add3 = Adder(base: 3) add3(10) // => 13
3:50 AM
いわゆる関数オブジェクト、Swiftの型システム的にはnominalな関数型(現状はstructural only)とも言えそう
Avatar
Scalaのapplyメソッド、Kotlinのinvokeメソッドと同じ感じっぽい
12:58 AM
Scalaのapplyは中のPrior artに書いてあった (edited)
Avatar
omochimetaru 3/20/2019 1:01 AM
提案通りcallキーワードを導入するのが良いと思う
1:01 AM
dynamicCallableでcallって言葉採用されてるし
1:03 AM
このスレ、ピッチ自体だけじゃなくて、コアチームがcompound typeのジェネリクスやプロトコルサポートの話してる struct BoundClosure<T, F: (T) -> ()>: () -> () { var function: F var value: T call() { return function(value) } }
1:05 AM
↑関数型がプロトコルの位置にある
Avatar
Hi all, There are property implementation patterns that come up repeatedly. Rather than hardcode a fixed set of patterns into the compiler, we should provide a general "property delegate" mechanism to allow these patterns to be defined as libraries. The complete proposal fol...
11:18 PM
property behaviorスレがどんどん伸びる
Avatar
norio_nomura 3/23/2019 4:28 AM
面白い
Avatar
Property DelegatesのPRにmacOSとUbuntu 16.04のtoolchainが来てる。 https://github.com/apple/swift/pull/23440#issuecomment-475933741
This is the implementation of the Property Delegates feature currently being pitched on the forums. Or, you can read the proposal. The implementation has a few notable limitations: libSyntax/Swift...
Avatar
omochimetaru 3/25/2019 1:03 AM
これがあるとbotが作れるんですっけ?
Avatar
norio_nomura 3/25/2019 2:58 AM
とりあえずdocker imageは作りましたよ。まだbotにはしてない。 norionomura/swift:pr-23440
3:01 AM
swift-pr-toolchain的なボットを作ろうかどうしようか迷ってる。
3:03 AM
一つのボットアカウントで複数のtoolchainを切り替えられる岸川さん提供のボットの方が、仕組みは馴染むはず。
Avatar
omochimetaru 3/25/2019 3:32 AM
なるほどなるほど
Avatar
Kishikawa Katsumi 3/25/2019 4:36 AM
お、使えるようにしますかね。
4:37 AM
swift-PR-23440-175-ubuntu16.04 か。名前の規則が違うからちょっと作業必要すね。家でゆっくりやるかな。
Avatar
norio_nomura 3/25/2019 6:52 AM
swift-PR-23440-177-ubuntu16.04 がビルド中ですね。 https://ci.swift.org/job/swift-PR-toolchain-Linux/177/
Avatar
norio_nomura 3/25/2019 7:34 AM
docker imageを更新しました。 norionomura/swift:pr-23440
7:34 AM
ビルドナンバー付きタグ norionomura/swift:pr-23440-177 でも使えます。
Avatar
あ、PR中の @swift-ci please build toolchain で作成される ubuntu 向けtoolchainのアーカイブは、 https://swift.org/downloads で配布されるものと違って、アーカイブ内のファイルはタグと同名のディレクトリに入っていない点に注意が必要です。 tar -xvzf $SWIFT_ARCHIVE_NAME.tar.gz --directory / --strip-components=1とかすると、/bin/swiftとか書き込むことになります。
Avatar
@swift-5.0.3 import Foundation print(ProcessInfo.processInfo.environment["SWIFT_VERSION"]!)
Avatar
5.0-RELEASE
Avatar
The review of SE-0244: Opaque Result Types has concluded and the proposal has been returned for revision.
10:11 AM
ORT、return for revision
10:12 AM
「言語の大きな機能になるからFuture directionについてgenerics manifstoみたいにしっかり書いて」て感じ?
Avatar
まずは "reverse generics" を導入するのがいいと思う。
2:13 PM
すでにジェネリクスはあるわけだし。
Avatar
その先のORTですかね
Avatar
ORT だけじゃ多分↓とかできないし。 func makeAnimals() -> <A: Animal> (A, A) { return (Cat(), Cat()) }
Avatar
The review of SE-0253: Static callables begins now and runs through April 5, 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 your feedback private, directly to me as t...
12:38 AM
4/5まででstatic callableのレビュー
12:39 AM
こう、そこまでスレも伸びないままシュッと始まって期間も短いので、ほぼ内定してそう
Avatar
Kishikawa Katsumi 3/28/2019 8:45 AM
let inputRadius: CGFloat = 0 var radius = UInt32(floor(inputRadius * 3 * sqrt(2 * CGFloat.pi) / 4 + 0.5)) ^ このコードは、Xcode 10.1ならビルドできるけど10.2では The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions でビルドできない。
Avatar
omochimetaru 4/3/2019 6:28 AM
Hi Swift Community, The review of SE-0255: Implicit Returns from Single-Expression Functions begins now and runs through April 11, 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 ...
6:28 AM
関数でも1行ならクロージャみたいにreturn不要にしよう機能のレビュー
👌 2
6:29 AM
なかなか賛否両論 getterだけで良いなども
6:30 AM
個人的にはgetterのreturnは邪魔臭く感じる事多いけど、スレ読んでたら悩ましくなってきた
Avatar
Kishikawa Katsumi 4/3/2019 6:52 AM
Swiftは意図しない戻り値が返ることもなさそうだからいいんじゃないかな、という印象。
Avatar
omochimetaru 4/3/2019 6:53 AM
意図しない戻り値ってどういう意味ですか?
6:58 AM
rubyのArray.appendがVoidかと思ったら実はselfをreturnしてたみたいな?
Avatar
Kishikawa Katsumi 4/3/2019 6:59 AM
そうそう。 Swiftは戻り値をシグネチャに必ず書くから大丈夫かなっていう
6:59 AM
func remove(at i: Int) { array.remove(at: i) } ^ もしSwiftがこうだったら、意図しない結果になる、みたいな
Avatar
omochimetaru 4/3/2019 7:00 AM
なるほど
10:18 AM
さっきこのバグにハマった
Avatar
norio_nomura 4/5/2019 10:29 AM
Swift 5のString.Index周り、沢山バグあります。
Avatar
@Douglas_Gregor wrote the Generics Manifesto almost three years ago, which provided the roadmap for the core of Swift's protocols and generics features. Since then, we've implemented almost all of the basic model that it envisioned. Although there are further features we coul...
Avatar
omochimetaru 4/9/2019 1:28 AM
読んできた。めっちゃ長かった、情報量多すぎるけどこれはすごい
1:28 AM
全てのカオスが整理されてる
Avatar
ORTより先にReverseGenericsやで、という意思を感じるけどあってるかな
Avatar
omochimetaru 4/9/2019 1:37 AM
そうね まあ一応直交な話にはなってて some記法はあくまでGenericsから三角カッコを消して書きやすくするシュガー
1:38 AM
RevGencsは実装が決める型レベル抽象が今できないから足さなきゃねって位置付け
👏 1
Avatar
おk
1:38 AM
thx
1:39 AM
だいたいスッキリした
Avatar
omochimetaru 4/9/2019 1:39 AM
それ以外にもexitlのオープン構文、Generalized existential、anyの必須化、などもかかれてる
Avatar
しかしこれ風呂敷たたむの大変やね
Avatar
omochimetaru 4/9/2019 1:39 AM
全く新しいトピックはオープン構文じゃないかな
Avatar
それはgeneric manifestにあったやつかな?
Avatar
omochimetaru 4/9/2019 1:40 AM
あったんだっけ
Avatar
誰彼のドラフトかも、見た記憶はある
Avatar
omochimetaru 4/9/2019 1:40 AM
let <X: Collection> openedX = x // X is now bound to the dynamic type of x let start = openedX.startIndex let first = openedX[start] // OK, indexing X with a value of type X.Index, to get a result of type X.Element
Avatar
つまりExistentalがanyでかかれてGenericsがsomeのシュガーを持つ、と。めちゃくちゃわかりやすいんじゃないかなぁ
Avatar
omochimetaru 4/9/2019 1:41 AM
あとは
Avatar
既存の混乱も終焉を迎えるはずだ
Avatar
omochimetaru 4/9/2019 1:41 AM
some 記法のところで型パラが無名になる問題に対して
1:42 AM
func concatenate(a: some Collection, b: some Collection) -> some Collection where type(of: a).Element == type(of: b).Element, type(of: return).Element == type(of: b).Element
Avatar
お、上の構文の提案は私見たことないな。私が見たのはif letみたいなネストがあるやつ
Avatar
omochimetaru 4/9/2019 1:42 AM
このように、引数名から型を取ってきて指定できるようにする案
1:42 AM
これかなり良さそう
1:43 AM
あと、any必須化によって、exisだけに拡張が書けるようになる extension any Hashable: Hashable {
Avatar
where句出るなら無理にsome使わなくていいんじゃないのとはおもったけどw
Avatar
omochimetaru 4/9/2019 1:44 AM
読むときの間接度が1つ減るから良いと思うんだよね (edited)
Avatar
私は
Avatar
omochimetaru 4/9/2019 1:44 AM
「Tは第一引数」ってワーキングメモリ使わないといけない
Avatar
$0 $1 $2みたいな感じで良いかな?とは思った
1:45 AM
type(of)は長い
1:45 AM
無名型引数に対して連番ラベルを持って処理する
Avatar
omochimetaru 4/9/2019 1:46 AM
なるほど
Avatar
extension any Hashableは嬉しいなぁ
1:47 AM
結構ワクワクするねこれ
Avatar
omochimetaru 4/9/2019 1:47 AM
typeofはすでにある関数なのが良いと思う
1:48 AM
初見で読める
Avatar
関数の定義に関数使えるように見えてキチい
Avatar
omochimetaru 4/9/2019 1:48 AM
あと、ここに型レベル式が書ける拡張が期待できる
Avatar
それができるならそれでええんやが
1:51 AM
$0,$1...は結構いいかなと思ったんだがなぁ、デバッグしてたらτ0みたいなのはよく見るじゃん、それのイメージや
Avatar
omochimetaru 4/9/2019 1:52 AM
なんかシグネチャ変更時にズレて書き直すことになりそうなのが微妙なんだよな
1:52 AM
$とは記号変えて %a とか
Avatar
それは変えた方が良いのは同意
Avatar
omochimetaru 4/9/2019 1:53 AM
type(of:)の省略記号としての前置演算子とか?
1:53 AM
うーんでもこういうのはやりすぎるとPerlになるから悩ましい。
Avatar
前置は良さそうだけどスッと理解できる奴だと良いね
Avatar
omochimetaru 4/9/2019 1:54 AM
extension any Hashable: Hashable { static func ==(a: any Hashable, b: any Hashable) -> Bool { return AnyHashable(a) == AnyHashable(b) } func hash(into: inout Hasher) { AnyHashable(self).hash(into: &into) } } これはめっちゃ綺麗で
1:55 AM
exitentialのself conformanceの定義付けと実装が
1:55 AM
与えられるようになるから、self-conformanceよくわからん問題が
👏 1
Avatar
おおすごい
Avatar
omochimetaru 4/9/2019 1:55 AM
一気にわかりやすくなると思う
1:55 AM
これで実装を与えられるならself-conformanceするってことだから。
Avatar
Errorがコンパイラ特別扱いじゃなくなる
Avatar
omochimetaru 4/9/2019 1:56 AM
AnyHashableがめっちゃ良い例で、これは普通のEquatableよりゆるくなって型の同一性がないから、型比較(暗黙変換を考慮した謎体系) (edited)
1:56 AM
を実装しなきゃいけないということがよくわかる
1:56 AM
Errorの場合は extension any Error : Error {} (edited)
1:56 AM
って空で書けばいいわけだな
Avatar
んだね
Avatar
omochimetaru 4/9/2019 1:57 AM
まあ、空になる場合は自動self-conformanceってのもありだと思う。
1:57 AM
Error特別対応を一般化する。
Avatar
明示的にやった方がいい気はするけど
Avatar
omochimetaru 4/9/2019 2:03 AM
type(of: return).Element
2:03 AM
これだと引数名にreturnが使えなくなるから
2:05 AM
resultType.Element とか? うーん。
Avatar
omochimetaru 4/9/2019 2:12 AM
>>14でDanielさんが同じこというてる
2:13 AM
>I don't think this is better than the &Rust syntax, but another potential way to go is the positional argument syntax: func concatenate(a: some Collection, b: some Collection) -> some Collection where $0.Element == $1.Element, $2.Element == $1.Element
Avatar
引数と返り値で添字つけるとわかりやすくなるかな、 $A0, $A1, $R0, $R1, ...
3:49 AM
わからん🙃
Avatar
omochimetaru 4/10/2019 2:37 AM
It is a wonderful document, with many of the previous discussions being neatly organized. The ORT discussion was very complicated, but I think the extension of type system by concept of reverse generics and concise notation with the some keyword are very beautiful. If the s...
Avatar
これほぼ完璧なドキュメントだな。ORT関連の議論が簡潔かつ網羅的にまとめられている。
Avatar
うんうん
Avatar
We think this is a reasonable first step because it directly addresses the biggest functionality gap in the generics model.
この this は ORT だと思うけど、これについては最初に reverse generics をやった方がいいと思うなぁ。
Avatar
あとあとまとまるならどこから来ても良くないですか?
12:08 PM
先のプランもあれば内部実装の設計的な後戻りも避けられるだろうし。 (edited)
Avatar
まあ Core Team の人たちはすごいから先まで見通せるかもしれないけど、考慮漏れがないように reverse generics からやった方が無難な気が。あと、すでにジェネリクスはあるから構文的にも新しい ORT から手を付けるより、 reverse generics から入った方が過程も自然な状態を保てそう。
Avatar
I really love the direction. some and any seems perfect keywords. I think explicit existential types are worth breaking source compatibility. It also helps to notify people who are familiar with languages like Java that protocols in Swift are different from interfaces in thos...
Avatar
Hi Swift Community, The review of SE-0244: Opaque Result Types has reopened and runs through April 17, 2019. The previous review was returned for revision, with the goal of setting the proposal in a wider context of future possible directions for the generics system. Since ...
Avatar
はやい…。
Avatar
omochimetaru 4/11/2019 1:24 AM
17日までで再レビューですか、展開がはやい
Avatar
omochimetaru 4/11/2019 1:41 AM
モチベーションの章とか全く違う話になってる
Avatar
凄い展開だw
Avatar
omochimetaru 4/11/2019 2:15 AM
That makes opaque result types somewhat less compelling for the compactMap example presented in the introduction, because one cannot have compactMap be marked @inlinable with an opaque result type, and then later change the underlying concrete type to something more efficient.
2:16 AM
これがあるからシンプルな関数の返り値の例をintroから外したのかな
Avatar
omochimetaru 4/11/2019 2:50 AM
@koher >>5の書き込みですけど、システム上>>4へのレスになってるけど、内容としてはスレッドへの投稿だと思うので、クリックするReplyボタンを間違えたかも?
2:51 AM
これを食らうと、フォーラムのシステムでレス先のユーザには通知が行っちゃうんですよ。(昨日食らった)
2:52 AM
あ、あってるのか、これは。
2:53 AM
>>4じゃなくて>>2か
Avatar
うん、これは書かれてたコメントへの reply
2:59 AM
I strongly agree with adding opaque result types to Swift. However, supporting "reverse generics" first seems better for me because Swift has already supported generics. I think having generics and "reverse generics", in the transition period to add features step by step, m...
🙇 1
Avatar
There's no IsOptional type of protocol (in the language or standard library) unless I write my own to add it to the opaque type signature
https://forums.swift.org/t/se-0244-opaque-result-types-reopened/22942/10 Optional 互換のプロトコルがないという視点はおもしろい気がする。ちょっと話は変わるけど、もし OptionalProtocol があれば↓みたいなこともできる? enum IndirectOptional<Wrapped>: OptionalProtocol { case none indirect case some(Wrapped) }
What is your evaluation of the proposal? Overall +1, but deferring handling Optionals will impede my ability to fully make use of this feature. For better or for worse, Optionals have a special place in the type system, and there's this weird boundary with them: There's ...
3:31 AM
indirect な Optional ときどきほしくなる。
Avatar
omochimetaru 4/11/2019 3:32 AM
OptionalProtocol無いと書けないextensionとかありますね
3:33 AM
ん、それはなにか意味ありますか?>IndirectOptional
Avatar
うん、プロトコルがない不便さは前からあったけど、 ORT 絡みでの意見は初めて見た気がする。
Avatar
omochimetaru 4/11/2019 3:34 AM
I have been involved in several separate related draft proposals for discussions that were cut off about 4 months ago. I believe they meet the criteria for Stage 2, but I'm doing a poor job presenting them coherently on-list. Because of that, I'm going to start over here, ...
3:35 AM
Ericaさんがピッチ立ててて、ユーザ定義enumでもif let できるとかアイデアが出てるけど話題止まってるんよな
Avatar
@swift-5.0.3 struct Foo { var foo: Foo? }
Avatar
exit status: 1 with stderr:<stdin>:2:9: error: value type 'Foo' cannot have a stored property that recursively contains it var foo: Foo? ^ <stdin>:2:9: note: cycle beginning here: Foo? -> (some(_:): Foo) var foo: Foo? ^
Avatar
omochimetaru 4/11/2019 3:35 AM
このORTでの意見は単に Optional<some Collection> ができないから
Avatar
@swift-5.0.3 enum IndirectOptional<Wrapped> { case none indirect case some(Wrapped) } struct Foo { var foo: IndirectOptional<Foo> }
Avatar
no output
Avatar
omochimetaru 4/11/2019 3:35 AM
OptionalなProtocol + associated typeにすればできるって事?
3:36 AM
some OptionalOfCollection でごまかしたい? (edited)
Avatar
いや、プロトコルは、 OptionalIndirectOptional を統合的に扱う仕組みが必要だろうなというくらいのことしか考えてない。
3:36 AM
Array だったら再帰できるのに、 Optional で再帰できないの辛い。 (edited)
Avatar
omochimetaru 4/11/2019 3:37 AM
あ〜
3:37 AM
普通のOptionalだと自分をフィールドに持てないのか。
Avatar
うん。
Avatar
omochimetaru 4/11/2019 3:39 AM
Mordiiさんの意見に関しては
3:39 AM
Optional<some Collection> は あとで対応するって書いてあるから
3:39 AM
それでいいような。待てなければ、自前定義でもできるし。
Avatar
あとで対応せずに先にやってって言ってるんじゃないかな?
Avatar
omochimetaru 4/11/2019 3:40 AM
but deferring handling Optionals will impede my ability to fully make use of this feature.
3:40 AM
ああ、こっちが言いたい事か。
Avatar
いずれにせよ reverse generics 先にやれば解決なんだけど、いきなり reverse generics やるのはきついのかな?実装が。 (edited)
Avatar
omochimetaru 4/11/2019 3:40 AM
少なくとも現時点のORTはすでに完成してますからね。
3:41 AM
Optional対応とかRevGenes対応をすると遅延するのは間違いない
3:41 AM
ちょっとずつ機能ができ次第入るのと
3:41 AM
完璧なものが一気にきてほしいのかの
3:41 AM
違いな気がしていて
3:41 AM
そういう判断は実装者に任せたらいいんではないかなあと思う
Avatar
ただ、 ORT 実装したときってまだ reverse generics っていう概念が示されてなかったと思うから
Avatar
omochimetaru 4/11/2019 3:42 AM
まあ、残りの部分も早くして!って急かすことに意味はあるけど。
Avatar
それに耐えうる汎用度で今の実装がされてるか疑問が。
3:43 AM
こんなややこしい機能を、最終的な汎用的な形に至らない部分的な形で実装しても、 ABI がぐちゃぐちゃになったりしないのかなぁ。
Avatar
omochimetaru 4/11/2019 3:44 AM
静的にはspecialize最適化と一緒で
3:44 AM
動的にはExistential Containerと一緒だから
Avatar
ABI 安定化前はそれでよかったと思うんだけど、いくら additive とはいえ、 ORT は reverse generics のシュガーなのに ABI は二通りあるとかなりそうな気が。
Avatar
omochimetaru 4/11/2019 3:47 AM
型の決まり方っていうコンパイルステージの新しさしかなくって、 実行時モデルとしては ジェネリックな T 型 の resilient版のコードや Existentialと変わらない気がするんですよね
3:48 AM
同一モジュールでコードが見える場合やinline化可能な場合に生じるのはspecialize最適化と同じだし。
3:49 AM
実装で大変なのは型解決中のSemaのデータ構造の方に見える
Avatar
同一モジュール内は露出していいと思うんだけど、モジュールをまたぐときに reverse generics 独自の表現になるんじゃない?
Avatar
omochimetaru 4/11/2019 3:50 AM
そのモジュールをまたぐときはExistentialと同じ仕組みでいけません?
3:51 AM
「どの関数から来た」って情報はあくまで別モジュールで型チェックするときに引っ張れればよくてコンパイル後は消える。
3:52 AM
Existentialと同じ仕組み=(値本体, 真の型のメタタイプ, そのPWT...)
Avatar
コンパイル後に消えたら、コンパイル単位が異なるときに existential 扱いにされたら↓みたいな型チェックができなくない? func foo1() -> <A: Animal> A { ... } func foo2() -> <A: Animal> A { ... } var a = foo1() let b = foo2() a = b // NG
Avatar
omochimetaru 4/11/2019 3:53 AM
コンパイル後じゃないや、実行時。
3:53 AM
「コンパイルされたライブラリ」にはヘッダーとしてその情報は残ってる。
Avatar
実行時は消えていい気がする。
3:56 AM
うーん、ヘッダーに型情報があればそれで問題ないのか・・・
Avatar
omochimetaru 4/11/2019 3:58 AM
もしかして、返り値でexistentialで返すときに、タプルの中身を個別の引数での参照返しになってて、 (edited)
3:58 AM
Optionalのフィールドみたいに、型の中に値として持つ表現がまだ決まってないんかな
3:58 AM
あ、でも、var a = foo1() の形のときはローカル変数に展開してるはずか。
3:59 AM
今度調べてみよう
4:05 AM
tackling "reverse generics" first can prevent lack of consideration about internal implementation.
4:05 AM
これに返信もらえるといいですね
4:07 AM
いくら additive とはいえ、 ORT は reverse generics のシュガーなのに ABI は二通りあるとかなりそうな気が。
↑ここまで書いとけば良かったかも
Avatar
まあとりあえず様子見してみます。気持ちとしては reverse generics 先がいいんじゃないのと思ってるけど、別に ORT からでも手を付けてくれたら全然いいしね。↓はその通りだと思うし。
そういう判断は実装者に任せたらいいんではないかなあと思う
4:12 AM
ORT レベルじゃなくて、フルの reverse generics 持った言語って何かあるのかな?
Avatar
omochimetaru 4/11/2019 4:13 AM
実行時の動的な表現は無いけど
4:13 AM
C++のテンプレートは同じ事ができてる気がする
4:14 AM
Altenative Consideredの
4:14 AM
We could theoretically address the verbosity problem in its full generality and without introducing new type system features by allowing return types to be inferred, like C++14's or D's auto return types: func jsonBlob() -> auto { ... }
4:15 AM
あーまあ真の型がテンプレートとしては見えないけど展開されちゃうからfoo1()とfoo2()が相互に互換できたりするかも?
4:15 AM
でもまあ実装側から総称型が決まるって意味では似てます
Avatar
それだと内部実装変えて型変わったときにコード壊れそう
Avatar
omochimetaru 4/11/2019 4:16 AM
そうですね、でも、C++はそもそも
4:16 AM
ジェネリックなコードは常にヘッダーで露出して、全部リコンパイルするのが大前提で
4:16 AM
そうじゃないやり方は存在してないので。
Avatar
うーん、実装が露出してることと、型システム上で型が露出してることはまた別な気がする。
Avatar
omochimetaru 4/11/2019 4:18 AM
SwiftはC++の理想のバイナリに対してモジュール分割を導入してる点で新しいから
4:18 AM
そういう意味では先行事例は無い気がする
4:18 AM
そもそもSwiftが目指してる設計の方向性が完全に新しい。
Avatar
戻り値 auto よく知らないけど、単に戻り値を記述しなくていいというレベルの簡略表現なわけではない?まあでも、実装が型を決めるという意味では通常の auto の dual になってるのか?
4:19 AM
Rust も ORT はできてるけど reverse generics はできてないのかな?
Avatar
omochimetaru 4/11/2019 4:19 AM
これはテンプレートのsugarになってるはずで
4:20 AM
関数宣言の構文において、先頭の戻り値型をautoもしくはdecltype(auto)とすることで、戻り値の型が関数のreturn文から推論される。
4:20 AM
// C++14 template <class F> auto g(F f) { return f(); } (edited)
4:20 AM
//C++11 template <class F> auto g(F f) -> decltype(f()) { return f(); }
4:22 AM
↑あ、この例はreverseじゃないですね。
4:24 AM
static int static_value = 3; auto f() { return static_value; } ↑これは実装から決まってる
Avatar
はじめまして。
1:10 PM
ゴールデンウィークに東京でSwift勉強会を開催するのですが、告知はどのチャンネルでするのがよいでしょうか?
Avatar
generalかzatsuな気がします
Avatar
zatsuで告知しました😃
1:06 AM
ありがとうございます!
Avatar
omochimetaru 4/12/2019 1:52 AM
>> 47 Joe_Groff
The runtime support I'm implementing is being done with an eye toward supporting generalized opaque types in the future, so if all goes well, there won't be further runtime deployment constraints on generalizing the feature (except maybe for debugger and tooling support).
(edited)
Avatar
omochimetaru 4/12/2019 3:33 AM
A continuation of #21137. This branch adds "proper" resilience support. Opaque types can now enter the SIL type system, and will be able to be represented at runtime with opaque accessors...
3:34 AM
↑これ手元でビルドしようとしてるけどなかなかうまくいかない。 関連リポジトリのチェックアウトするリビジョンがまずいんだろうけど、どうすればいいんだ?
3:36 AM
$ utils/update-checkout --tag swift-DEVELOPMENT-SNAPSHOT-2018-11-30-a $ utils/build-script --xcode --debug --skip-build-benchmarks --jobs 4 ... Ld /Users/omochi/work/swift-source-ORT/build/Xcode-DebugAssert/swift-macosx-x86_64/Debug/lib/swift/macosx/x86_64/libswiftPhotos.dylib normal x86_64 clang: error: no such file or directory: '/Users/omochi/work/swift-source-ORT/build/Xcode-DebugAssert/swift-macosx-x86_64/Debug/lib/swift/macosx/x86_64/libswiftAVFoundation.dylib' clang: error: no such file or directory: '/Users/omochi/work/swift-source-ORT/build/Xcode-DebugAssert/swift-macosx-x86_64/Debug/lib/swift/macosx/x86_64/libswiftCoreLocation.dylib' clang: error: no such file or directory: '/Users/omochi/work/swift-source-ORT/build/Xcode-DebugAssert/swift-macosx-x86_64/Debug/lib/swift/macosx/x86_64/libswiftCoreMedia.dylib' ...
Avatar
norio_nomura 4/16/2019 1:51 AM
The review of SE-0258: Property Delegates begins now and runs through April 23rd, 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 your feedback private, directly to me...
Avatar
omochimetaru 4/17/2019 8:42 AM
SE-0258読んだ。複雑な仕様になったけどなんとか要望を全部まとめきった感じだ・・・
Avatar
Proposal Returned to Pre-Review Discussion Thank you to everyone who has participated in the review of this proposal. I am thrilled to see the amount of passion and energy everyone has in making Swift a better language. This has been a polarizing discussion. It also has no...
Avatar
omochimetaru 4/19/2019 1:07 AM
珍しい感じの展開だ
Avatar
omochimetaru 4/19/2019 1:15 AM
SE0250の決はまだかなあ
Avatar
omochimetaru 4/24/2019 2:02 AM
funcでも1行ならreturnが省略できるようになった #swift https://t.co/pWDXAfc6mu
🙌 4
👍 2
Avatar
omochimetaru 4/25/2019 3:21 AM
3:21 AM
なにこれ・・・・
3:23 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
3:25 AM
https://github.com/apple/swift/blob/e68a2330fe3bff37935d9cb6759aa8c9ccb9d2ea/lib/AST/ASTPrinter.cpp#L4249 なんですかねw 「後で考えるとりあえずこれで」感
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 4/25/2019 3:25 AM
When printing a swiftinterface, represent opaque result types using an attribute that refers to the mangled name of the defining decl for the opaque type. To turn this back into a reference to the ...
3:29 AM
A continuation of #21137. This branch adds &quot;proper&quot; resilience support. Opaque types can now enter the SIL type system, and will be able to be represented at runtime with opaque a...
3:29 AM
レビューではツッコミなしか〜
Avatar
omochimetaru 4/25/2019 3:45 AM
This is necessary because: func foo() -&gt; some P func foo() -&gt; some P theoretically defines two distinct return types, but there&#39;d be no way to disambiguate them. Disallow ove...
3:46 AM
Opaque Result Type を持つ関数が、返り値の型のジェネリックシグネチャをmanglingに含めていなくて
3:46 AM
返り値オーバーロードができない(コンパイラクラッシュ)んだけど
3:46 AM
それを正式にsemaで禁止するようにするPR↑ (edited)
3:46 AM
未実装なのかと思って様子を見てたけど、意図的な設計だったっぽい
3:47 AM
I was also trying to prevent:
func foo() -> some P func foo() -> some Q
since there would still be no way to disambiguate these.
(edited)
3:47 AM
これ正しいのかなぁ
3:47 AM
特にGenericsの場合はシグネチャがオーバーロードに絡んでるんだけど
3:48 AM
ORTがReverse Genericsのsugarであるという解釈の元で
3:48 AM
おかしくならんのだろうか
Avatar
Kishikawa Katsumi 4/29/2019 10:25 AM
https://forums.swift.org/t/adding-more-data-structures-to-the-standard-library/23651 私ももう少しリッチなデータ構造が標準ライブラリにあればいいと思う。
I'm studying for job interviews for Swift positions by completing code problems. By far the most painful part of this preparation is the dismal state of data structures in Swift. If I were programming in Java (which I really rather wouldn't), I would have easy access to... ...
Avatar
以前OrderdDictがほしくて作ったけど、計測したらオーバーヘッドが大きくて意味なかったんですよね〜 実装が悪いのもあるとしても、そういうケースは多そうと思った
10:56 AM
その時の意味が出てくるのは要素数5000件ぐらいでした
Avatar
Kishikawa Katsumi 4/29/2019 12:22 PM
OrderdDictが要素数に応じてパフォーマンスが劣化していくのは仕方ないんじゃないかな。 実際に標準ライブラリに入ったときにどれくらいになるかはともかく、自分で作るしかないよりは、選べる方がいいんじゃないかな。 とにかくLinkedListくらいは入ってほしい。
Avatar
あいえ、5000件を超えるとパフォーマンスが良くなるという意味です
12:23 PM
それより小さい時はタプルのArrayの方が早いんです。
12:26 PM
公式に提供されるのは望ましいけど、標準ライブラリだと外せないから、外部パッケージがよいと思うんですけど
Avatar
Kishikawa Katsumi 4/29/2019 12:26 PM
へえ。5000件くらいまでならHashより速いのか。 (edited)
Avatar
Hashと、リンクリストのためのメモリアロケーションがかなり遅いですね Arrayはメモリ局所性が効いててかなり早い
Avatar
Kishikawa Katsumi 4/29/2019 12:28 PM
特殊なやつは別ライブラリでいいんですけど、今のビルトインのデータ構造はさすがにプリミティブすぎると思うので、もう少し増えていいと思います。
Avatar
まあ、たしかに、そうですね。いまはArray Dict Setしかないのは、粗いですね
👍 1
Avatar
Queue がほしいと思うことはよくありますね。
Avatar
omochimetaru 5/7/2019 1:07 AM
It is my pleasure to announce our two GSoC students for 2019! Don Cung (@cungd) will be working on Scalability benchmarks for the Swift Standard Library with Karoy Lorentey (@lorentey) as his mentor. Jan Svoboda (@jansvoboda11) will be working on Integration of libSynta...
1:07 AM
Jan Svoboda (@jansvoboda11) will be working on Integration of libSyntax with the compiler pipeline 9 with Rintaro Ishizaki (@rintaro) as his mentor.
1:09 AM
りんたろープロジェクトめっちゃ大変そう
1:12 AM
型付けされたSwiftSyntaxがあるといろんな応用がありそうで期待
Avatar
唯一 Hard が付いてるw Expected difficulty Medium/Hard https://swift.org/gsoc2019/#integration-of-libsyntax-with-the-rest-of-the-compiler-pipeline
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
頑張ってメンターやります🙂
👍 1
swift 4
Avatar
omochimetaru 5/7/2019 3:28 AM
Today, we’re announcing that the next release after .NET Core 3.0 will be .NET 5. This will be the next big release in the .NET family. There will be just one .NET going forward, and you will be able to use it to target Windows,
3:29 AM
Objective-C and Swift interoperability will be supported on multiple operating systems.
3:29 AM
すごいことかいてある
Avatar
行列型も欲しいですかね(特にこれからARとか推していくのに、3Dが入ってきて行列式を頑張って配列で書くとパフォーマンスとセキュリティーのバランスが難しい
Avatar
omochimetaru 5/7/2019 5:03 AM
僕はGLKitのGLKMatrix4を使ってます Linuxだと無いですね
Avatar
でもmultiple operating systemsというのは、macOSとiOSだけでもいいのか…
Avatar
omochimetaru 5/7/2019 5:13 AM
あ、たしかに。 Windowsを想定してたけどw
Avatar
omochimetaru 5/8/2019 1:04 AM
Hi Swift Community, The review of SE-0260: Library Evolution for Stable ABIs begins now and runs through May 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 you...
1:06 AM
LibraryEvolutionのレビュー
Avatar
omochimetaru 5/8/2019 1:38 AM
「新しくLibraryEvolutionモードでのビルド」が追加されて LE無効(デフォルト) ・enumはfrozen ・structはfrozen LE有効(標準ライブラリはこっち) ・enumはresilent ・structはresilent になり、LE有効時において、@frozen をつけると、enumやstructをfrozenにできる
1:43 AM
iOSアプリの場合は書き出されたアプリに内包されるライブラリだけを後から差し替えることはないから関係なさそうだな
Avatar
omochimetaru 5/8/2019 1:55 AM
この辺の値型のresiliencyに関してはC/C++/Rustはやってないので、 柔軟さと高速さを両立するSwiftらしさを感じる
Avatar
Kishikawa Katsumi 5/9/2019 7:06 AM
Set同士は + で足せないんだな。
Avatar
omochimetaru 5/9/2019 7:07 AM
できても良さそう
Avatar
そうすると * で intersection をとるんでしょうか?
Avatar
論理積和と対応するから&|のほうが良さそう? (edited)
Avatar
omochimetaru 5/9/2019 7:09 AM
なるほど。
Avatar
が良い?
7:12 AM
&&& )や ||| )なので だけあっても微妙そうだな・・・。
Avatar
英字で一発で入力できないので運用上厳しそうですね…
Avatar
謎記号が増える理由…
Avatar
omochimetaru 5/10/2019 6:00 AM
Receiver Closures Hello, I would like to get some feedback on a pitch idea. Idea allow specifying the receiver of a closure. (what a closure is being called on) This would modify how self behaves inside a closure body. Kotlin already has something similar Higher-Order Fun...
6:01 AM
Kotlinにあるようなレシーバクロージャの話 ラムダ式がselfを引数にとって、その中でselfが省略できる
Avatar
Xcode 10.2 (Swift 5)で U+FEFF (ZERO WIDTH NO-BREAK SPACE)から始まるStringをNSStringに変換するとU+FEFFが消えるのですが、これってなんなのかわかる方いらっしゃいます? バグ? import Foundation let bom = "\u{feff}" bom.count // -> 1 (bom + "abc").count // -> 4 NSString(string: bom).length // -> 0 NSString(string: bom + "abc").length // -> 3 NSString(string: "a" + bom + "bc").length // -> 4
Avatar
omochimetaru 5/11/2019 4:58 PM
先頭にある時だけ消えちゃうんですね
Avatar
そう、途中とかだと消えない。
10:55 PM
U+FEFFはいわゆるUTF8のBOMなんでなんかへんな処理が走ってそう。
Avatar
omochimetaru 5/13/2019 1:41 AM
UTF-8は本当はBOMは無いので、普通のUTF-16のBOMですね
1:44 AM
BOMは先頭にあるときだけエンコードを示す非コンテンツ部分だから、初期化時に捨てるのは正しい気もするけど、 "a"+ bomのときに消えないのはStringの結合処理とNSStringの初期化処理でポリシーがバラバラそう
Avatar
文字列連結で(UTF8)BOMが消えないのはそのせいで2chブラウザのSevenFourがバグっててパッチ書いた記憶がある
7:11 AM
仕様?
Avatar
omochimetaru 5/13/2019 7:11 AM
bugsで聞いてみるのが良さそうだなあ
Avatar
2chのスレが残ってた! 文字列連結は全然関係なかった。 intel mac移行時のエンディアン問題だった。すみません。
Avatar
omochimetaru 5/14/2019 1:13 PM
import Foundation struct HB : Decodable { var heartbeatInterval: Int enum CodingKeys : String, CodingKey { case heartbeatInterval = "heartbeat_interval" } } let json = #"{ "heartbeat_interval": 30 }"# let d = JSONDecoder() d.keyDecodingStrategy = .convertFromSnakeCase let data = json.data(using: .utf8)! let x = try d.decode(HB.self, from: data) dump(x)
1:14 PM
↑CodingKeysでスネークケースにするのと、keyDecodingStrategyでスネークケースにするのを同時に使うと、デコードに失敗するんだけど、どういう考え方なんだ・・・?
1:15 PM
両方考慮される結果、CodingKeysはスネークケースを期待してて、Decoder側はJSONのスネークケースから変換されたキャメルケースを投げてて、ミスマッチする?
Avatar
omochimetaru 5/15/2019 6:45 AM
なんか最近 Optional<X> を書くところで X のスタティックメンバがちゃんと候補予測される気がする
Avatar
Codableのこの前ハマりました…heartbeatIntervalをCodingKeysのrawValueにしないといけないんですよねこれ
Avatar
omochimetaru 5/15/2019 7:18 AM
やっぱりそうなのか〜
7:18 AM
あ、自分の件はconvertFromSnakeCaseを使わない方で対処しました。
Avatar
僕もconvertFrom~~で何度か痛い目に遭ったので使わない方向に寄せてます
Avatar
omochimetaru 5/15/2019 7:21 AM
この前OSSFoundationのバグ直してたね。 (edited)
Avatar
それです
7:24 AM
JSONDecoder側でキーのケースを決めるべきなのか?という気持ちになってきた
Avatar
omochimetaru 5/17/2019 3:40 AM
The second review of SE-0253 - Callable values of user-defined nominal types ran through May 13. Compared to the first round, the feedback was relatively light, mostly focused on the options of how to spell the callable member, more discussions of a @callable attribute, man...
3:40 AM
static callableが通ったけど func callFunction になったらしくて
3:40 AM
モヤモヤコメントがついてる。
3:41 AM
曰く func call だと既存の利用と衝突して予期せずこの機能が発動しちゃうのを避けるためらしい
Avatar
初期の提案+@dynamicCallable側を見直して
5:58 AM
init() {} subscript() {} call() {} dynamicallyCall() {}
5:59 AM
となってくれるのが個人的希望でした。
Avatar
omochimetaru 5/17/2019 6:00 AM
最初は call() {} だったけど 後に func call() {} になりましたね
Avatar
ですね。
Avatar
omochimetaru 5/17/2019 8:47 AM
@swift-5.1.5 protocol P { func print() } extension Int : P { func print() { Swift.print("Int \(self)") } } protocol PHolder { associatedtype PType: P func take1() -> PType func take2() -> PType } struct S : PHolder { func take1() -> some P { return 3 } func take2() -> some P { return 2 } }
Avatar
exit status: 1 with stderr:<stdin>:16:8: error: type 'S' does not conform to protocol 'PHolder' struct S : PHolder { ^ <stdin>:10:20: note: ambiguous inference of associated type 'PType': 'some P' vs. 'some P' associatedtype PType: P ^ <stdin>:20:10: note: matching requirement 'take2()' to this declaration inferred associated type to 'some P' func take2() -> some P { ^ <stdin>:17:10: note: matching requirement 'take1()' to this declaration inferred associated type to 'some P' func take1() -> some P { ^
Avatar
omochimetaru 5/17/2019 8:48 AM
思ってたのと違う・・・
Avatar
omochimetaru 5/17/2019 8:58 AM
@swift-5.1.5 let strings: some Collection = ["hello", "world"]
Avatar
exit status: 1 with stderr:<stdin>:1:32: error: cannot convert value of type '[String]' to specified type 'some Collection' let strings: some Collection = ["hello", "world"] ^~~~~~~~~~~~~~~~~~ as! some Collection
Avatar
omochimetaru 5/17/2019 8:59 AM
Proposalに出てくるコードすら通らないんだけど Status: Implemented (Swift 5.1) になってるのどういうことなんだ
Avatar
omochimetaru 5/17/2019 2:16 PM
@swift-5.1.5 func foo() -> some BinaryInteger { return 219 } var x = foo() x = 912 print(x)
Avatar
912
Avatar
omochimetaru 5/17/2019 2:20 PM
@swift-5.1.5 func foo() -> some BinaryInteger { return 219 } var x = foo() x = Int(912) print(x)
Avatar
exit status: 1 with stderr:<stdin>:3:5: error: cannot assign value of type 'Int' to type 'some BinaryInteger' x = Int(912) ^~~~~~~~ some BinaryInteger( )
Avatar
なんか最近 Optional<X> を書くところで X のスタティックメンバがちゃんと候補予測される気がする
Implicit member expression や enum element pattern 周りのコード補完に関しては 5.0 でかなり修正を加えていて、マシになってるとは思いますが、まだ改善中です。コード補完で必要な候補が出ない、使えない候補が出てくるなど、全部バグなので bugs に報告もらえれば嬉しいです!
🙂 2
Avatar
omochimetaru 5/19/2019 2:48 PM
やっぱ改良されてたんですね、ありがとうございます!
Avatar
omochimetaru 5/24/2019 5:58 AM
@swift-5.0.3 public class BaseView { } public class GenericView<T>: BaseView { } public class FinalView: GenericView<ContentForTheView> { } public class ContentForTheView { } extension ContentForTheView: InfoNeededByControllers { } public protocol ConditionallyConformed { } public protocol InfoNeededByControllers { } extension GenericView: ConditionallyConformed where T: InfoNeededByControllers { } open class BaseGenericController<T> where T: BaseView & ConditionallyConformed { } open class FinalController: BaseGenericController<FinalView> { public override init() { } } print(FinalController())
Avatar
exit status: 134 with no output
Avatar
omochimetaru 5/24/2019 5:58 AM
すごいバグだな
5:58 AM
failed to demangle superclass of FinalController from mangled name '\255\375\377\377y\223\374\377\377G' 2019-05-24 14:57:44.734494+0900 Sandbox_20190524145301[51985:24831300] failed to demangle superclass of FinalController from mangled name '\^A\M--\M-}\M^?\M^?y\^A\M^S\M-|\M^?\M^?G'
5:58 AM
↑手元
Avatar
RelativePointerのオフセットが間違ってる?
Avatar
omochimetaru 5/24/2019 6:05 AM
ランタイム関数のswift_conformsToProtocolが間違ってる事に起因するらしい
6:05 AM
Build a static archive that can be linked into executables and take advantage of the Swift runtime&#39;s hooking mechanism to work around the issue Doug fixed in #24759. The Swift 5.0 version o...
Avatar
__swift_hook ってなんですか?
Avatar
omochimetaru 5/24/2019 6:15 AM
ふっふっふ
6:15 AM
なんとlibSwiftCore.dylibには
6:15 AM
ランタイム関数を差し替える機能があるのだ
Avatar
www
6:16 AM
そんなハチャメチャ機能が必要になるタイミングあるんですか
Avatar
omochimetaru 5/24/2019 6:17 AM
それが初めて必要になったのがこのPRで
6:17 AM
Swift5.0ランタイムのバグを、パッチ版にすり替えるようにしてる。
6:17 AM
ただ、まあバグ修正で使うのは本命じゃなくて
6:17 AM
型システムが強化されたりしたときに
Avatar
あー、ランタイム側はsharedになったからか
Avatar
omochimetaru 5/24/2019 6:17 AM
実行時キャストとかの処理をアップグレードすることを想定しているっぽい
6:18 AM
そう、OSに同梱しちゃってるから
6:18 AM
過去に出荷した仕様で永久にロックされないようにしてある
Avatar
なるほど
Avatar
このバグ、Xcode 9の時代から存在してるんですよね… https://bugs.swift.org/browse/SR-10442 https://bugs.swift.org/browse/SR-5466
Avatar
Arrayをラップしてサイズ変更不可能なFixedSizeArrayを作ろうとしてるんですが、 memcpy(&array1, array2, count)のようにUnsafe*Pointerで渡すところだけができない気がしています。 言語的に拡張できないコンパイラ組み込みの仕様だと思っていますが合っているでしょうか?
Avatar
@t.ae 構文の話でなく渡す手段がほしいという意味であれば withUnsafePointer とか使ってできそうだけど構文の話かな?
Avatar
構文の話です。そのまま渡せるほうが良いと思うので。
2:49 AM
UnsafePointerだけならarrayのゲッタを生やせばいいんですがUnsafeMutablePointerは対応できないですね。
Avatar
withUnsafeMutablePointer を実装するか、 array セッターの willSet とかで count が変わってないことを precondition で確かめるかどちらかかな。
Avatar
arrayセッタ形式は試してみたことあるんですが書き込みが多いと結構な負荷になるんですよね。
Avatar
func memcpy<Element>(_ a: inout FixedSizeArray<Element>, _ b: FixedSizeArray<Element>) みたいなオーバーロードを作るとか。
Avatar
ライブラリとして公開することを考えると一般の場合で使えないとなので特別対応はだめですね。
Avatar
↑のオーバーロードもライブラリに含めるのは?
2:56 AM
あー
2:56 AM
memcpy だけじゃないって意味か
Avatar
はい。
Avatar
うーん、 withUnsafePointerwithUnsafeMutablePointerFixedSizeArray に実装するのがいいんじゃないかなぁ。 (edited)
Avatar
ところでこいつはImage型のバッファに使おうと思っていたんですが、Image.buffer自体を書き換えられた場合に対応できないことに気付いたので結局頓挫しました。
2:58 AM
この試行は以前にも同じことをした気がする……
Avatar
Image のバッファだったらセッター露出しなければ Array でいいんじゃないの? (edited)
Avatar
まぁそうなんですが
3:00 AM
・現状@inlinable public internal(set) が使えない ・書き込みのために専用のsubscriptを生やすのはちょっと不格好
3:01 AM
なのでどうにかできないかと考えている次第です。
Avatar
SwiftImage (旧 EasyImagy )では ImagewithUnsafeMutableBufferPointer とか付けてるよ。生でピクセル配列を扱いたいときとか用に。 https://github.com/koher/swift-image/blob/dev-0.7.0/Sources/EasyImagy/Image.swift#L58-L60
SwiftImage: A Swift library for image processing with Swifty APIs - koher/swift-image
Avatar
それはもちろん僕もつけてます。
3:02 AM
けどユーザーフレンドリーではないですよね?
Avatar
そうかなぁ。安全でない操作をする場合はむしろわかりやすい気がする。
3:03 AM
得られたポインタのライフサイクルもわかりやすいし。
Avatar
たとえばimage1の画素値を同サイズのimage2の画素値に足したい場合 image1.with~ { bp1 in image2.with~ { bp2 oin for i in 0..<count { bp1[i] += bp2[i] } } } (edited)
3:04 AM
のような多重ネストになるので (edited)
Avatar
通常は露出してはいけない内部的な存在を露出してパフォーマンス上のメリットを得るわけだから、そのことが API 名からもわかりやすく、クロージャにすることでライフサイクルもわかりやすくするのは良いことかと。
Avatar
露出してはいけないという視点を入れるとそうですね……悩ましい
Avatar
bp[2]bp2[i] の間違い?
Avatar
です。
Avatar
↑のような用途では += を提供するという方法もあるけど、画像に対して += を提供するのはあまり Swifty じゃない気がしてるのと、任意の演算をユーザー側で実現することができないから、 zip + (map or inout バージョンの map ) をパフォーマンスロスなく実現できる高階メソッドを提供するのがいいんじゃないかと最近思ってる。
3:08 AM
RGBA 型に + が定義されてるのはまだいいんだけど、 Image だとサイズが合わないと precondition に引っかかるのが辛い。
3:08 AM
サイズも型にできればいいけど。
3:09 AM
それか Swift for TensorFlow みたいな?
Avatar
ぼくのは+=導入してますね
3:09 AM
S4TFのどうなってるか知らないです
Avatar
SwiftImage は導入してたけど、なくそうかと検討中。 (edited)
3:10 AM
Swift for TensorFlow って行列のかけ算とかコンパイラが解析して型が合わない場合はエラーにするとかやろうとしてるんじゃなかったかな。 (edited)
Avatar
ああ、それは聞いた気がします。
Avatar
前試したときはまだできてなさそうだったけど、今はできてるのかな。
Avatar
依存型できたとしてSwift本体側に入るのはいつになるか……
Avatar
でもそういう部分は本体に戻すことを目標にしてたはずなので、可能性はあるかと。
3:14 AM
Finally, while TensorFlow is the reason we built this infrastructure, its algorithms are independent of TensorFlow itself: the same compiler transformation can extract any computation that executes asynchronously from the host program while communicating through sends and receives. This is useful and can be applied to anything that represents computation as a graph, including other ML frameworks, other kinds of accelerators (for cryptography, graphics, transcoding, etc), and general distributed systems programming models based on graph abstractions. We are interested in exploring new applications of this algorithm in the future. https://github.com/tensorflow/swift/blob/master/docs/DesignOverview.md#graph-program-extraction (edited)
Swift for TensorFlow Project Home Page. Contribute to tensorflow/swift development by creating an account on GitHub.
3:15 AM
Swift に戻したいとはここには書いてないか。でも一般的な用途まで視野には入れてるっぽい。
Avatar
omochimetaru 5/30/2019 3:21 AM
言語的に拡張できないコンパイラ組み込みの仕様だと思っていますが合っているでしょうか?
Arrayのポインタ化は特別対応でユーザ対応はできない
3:21 AM
普通に pointer プロパティを生やすのは?
Avatar
pointer プロパティなら withUnsafe***Pointer 系の方が安全なんじゃない?
Avatar
プロパティとして出すのはSwift的にはよろしくないのでは。
Avatar
omochimetaru 5/30/2019 3:22 AM
でも固定サイズなんですよね?
3:22 AM
ずっとアドレス変わらない。
Avatar
CoW で変わるんじゃない?
Avatar
omochimetaru 5/30/2019 3:22 AM
ArrayとかDataとかがwithXXXなのは
3:23 AM
そのストレージ領域が実際に永続保証されていないからで
Avatar
固定サイズだけど set はされるので。
Avatar
@koher と同じ考えです。
Avatar
omochimetaru 5/30/2019 3:23 AM
CoWで変わるってどういうことです?値型ってこと?
Avatar
少なくとも僕が話していたのは値型ですね。
Avatar
omochimetaru 5/30/2019 3:24 AM
値型ならだめですね
Avatar
あと、↓とかもあり得る。 let p: UnsafeBufferPointer<Int> do { let a: FixedSizeArray<Int> = ... p = a.pointer } // 解放 p[0] // 解放済み (edited)
Avatar
omochimetaru 5/30/2019 3:27 AM
そうですねえ
Avatar
withUnsafeMutableBufferPointers とかあればいいのかなぁ。 withUnsafeMutableBufferPointers(of: [a, b]) { pointers in for i in 0..<count { pointers[0][i] += pointers[1][i] } } (edited)
3:35 AM
あ、 Mutable が抜けた
3:35 AM
Buffer もいるかな。
3:36 AM
& じゃないとダメか。
Avatar
さらにUnsafePointerとUnsafeMutablePointerも分けたいよな……とか考えてそのアプローチは保留してます。
Avatar
そうだねぇ・・・。今は bMutable じゃなくていいもんね。
Avatar
ずっと上の話ですけどArrayにset/willSet/didSet生やすのって newValueoldValueのためにarray[i] = 0みたいな変更でもまるごとコピーされちゃって負荷大きいんですよね。 count不変だけならwillSetでカウントどっかに保存してdidSetでカウント比較とかできないかと思ったんですが newValue/oldValueに触れてなくても重いのでコピーされてそう。
3:42 AM
O(1)を期待してアクセスしたのにO(n)になっているということがありそう。
Avatar
omochimetaru 5/30/2019 4:00 AM
newValueやoldValueのためにarray[i] = 0みたいな変更でもまるごとコピーされちゃって負荷大きいんですよね。
これはそうですね ただ、arrayがcomputed propertyだったとして owner.array[0] = 0 みたいなケースでは CoW が効いてないかなあ
(edited)
4:05 AM
O(1)を期待してアクセスしたのにO(n)になっているということがありそう。
ありそうなので、なったら困るやつではやりたくないですね。
Avatar
func testFloor1() { func f(array: inout [Double]) { for i in 0..<array.count { array[i] = floor(array[i]) } } var array = [Double](repeating: 1, count: 3840*2160*4) measure { // 58ms f(array: &array) } } func testFloor2() { func f<T: FloatingPoint>(array: inout [T]) { for i in 0..<array.count { array[i] = floor(array[i]) } } var array = [Double](repeating: 1, count: 3840*2160*4) measure { // 264ms f(array: &array) } } floorがGenericかどうかで5倍も差がつく……
Avatar
omochimetaru 6/3/2019 8:40 AM
floorの呼び出し自体もFloatingPoint protocolのwitness呼び出しかな?
Avatar
Foundationにfloorが複数あるんですよね。 doubleをとるやつとFPをとるやつ
Avatar
omochimetaru 6/3/2019 8:40 AM
5倍ってスケールはまあそのくらいな感じはする
Avatar
https://github.com/apple/swift-evolution/blob/master/proposals/0246-mathable.md これにも入らないので独自にプロトコル作って頑張るしか (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 6/3/2019 8:42 AM
どういうこと?
8:42 AM
実用面で言えば-Oで解決する話ではない? (edited)
Avatar
ではないです。
8:42 AM
↑のテスト結果はリリースビルドでの結果です。
Avatar
omochimetaru 6/3/2019 8:45 AM
[omochi@omochi-iMac-PC43 fp]$ swift -O a.swift 0.02524399757385254 0.24626600742340088
8:45 AM
確かに手元で10倍差ついた
Avatar
FloatingPointバージョンはビット数やなんかに依存しない実装になっててそれで遅いって感じでしょうか。 (edited)
Avatar
omochimetaru 6/3/2019 8:46 AM
そもそも [Double]にspecializeされてないのか?
8:48 AM
いや、specializeはされてる
Avatar
silが全然違って参考にならない……
Avatar
omochimetaru 6/3/2019 8:50 AM
testFloor1の方は、fごとinline化されてる
Avatar
fは@inline(never)つけないとでしたね。
Avatar
omochimetaru 6/3/2019 8:54 AM
inline(never)つけたら、testFloor側は同じになった [omochi@omochi-iMac-PC43 fp]$ diff testFloor1.sil testFloor2.sil 1,2c1,2 < // testFloor1() < sil hidden @$s1a10testFloor1yyF : $@convention(thin) () -> () { --- > // testFloor2() > sil hidden @$s1a10testFloor2yyF : $@convention(thin) () -> () { 52,53c52,53 < // function_ref f1(array:) < %40 = function_ref @$s1a2f15arrayySaySdGz_tF : $@convention(thin) (@inout Array<Double>) -> () // user: %41 --- > // function_ref specialized f2<A>(array:) > %40 = function_ref @$s1a2f25arrayySayxGz_tSFRzlFSd_Tg5 : $@convention(thin) (@inout Array<Double>) -> () // user: %41 105c105 < } // end sil function '$s1a10testFloor1yyF' \ No newline at end of file --- > } // end sil function '$s1a10testFloor2yyF' \ No newline at end of file
8:56 AM
f1は80行、とspecialized f2は200行でだいぶ違うな
Avatar
Doubleのほうはfloor関係のこれしかなさそうですね。 // floor sil [readnone] [clang floor] @floor : $@convention(c) (Double) -> Double
8:57 AM
FPは↑がないので全く違う内容が実行されていそう。
Avatar
omochimetaru 6/3/2019 8:58 AM
specialized f2は // function_ref Double._roundSlowPath(_:) %112 = function_ref @$sSd14_roundSlowPathyys25FloatingPointRoundingRuleOF : $@convention(method) (@in_guaranteed FloatingPointRoundingRule, @inout Double) -> () // user: %113
8:58 AM
いかにも遅そうな関数が呼ばれてる
Avatar
FPには.round(RoundingRule)ってやつが生えてるのでそれにいってそうですね。
9:00 AM
Doubleの場合もfloorじゃなくてarray[i].round(.down)を使ったら同程度の速度になるみたいです。
Avatar
omochimetaru 6/3/2019 9:02 AM
FloatingPoint.floorの実装が見つけられない。
9:04 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
9:04 AM
これ??
Avatar
みたいですね。
Avatar
omochimetaru 6/3/2019 9:05 AM
tgmathってのはCのジェネリックなマクロセットらしい。
9:05 AM
同じ中身をSwiftソースで書いたものかな。
9:07 AM
あー
9:08 AM
_roundSlowPathは呼ばれてなさそうだ
9:08 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
9:08 AM
public mutating func round(_ rule: FloatingPointRoundingRule) { switch rule { case .toNearestOrAwayFromZero: _value = Builtin.int_round_FPIEEE${bits}(_value) case .toNearestOrEven: _value = Builtin.int_rint_FPIEEE${bits}(_value) case .towardZero: _value = Builtin.int_trunc_FPIEEE${bits}(_value) case .awayFromZero: if sign == .minus { _value = Builtin.int_floor_FPIEEE${bits}(_value) } else { _value = Builtin.int_ceil_FPIEEE${bits}(_value) } case .up: _value = Builtin.int_ceil_FPIEEE${bits}(_value) case .down: _value = Builtin.int_floor_FPIEEE${bits}(_value) @unknown default: self._roundSlowPath(rule) } }
Avatar
SILにでてきてるのそのままですね。
Avatar
omochimetaru 6/3/2019 9:08 AM
このswitch-caseが、f2にinline展開されてる
9:08 AM
このdefault-caseのコードが、SILで見えているんだ。
9:08 AM
これ、めちゃくちゃいけてないね
9:09 AM
呼び出してるのはfloorなのに、一度roundの呼び出しになって
9:09 AM
/// // Equivalent to the C 'floor' function: /// var z = 6.5 /// z.round(.down) /// // z == 6.0
9:09 AM
このモードに分岐で突入してから本当の関数を呼ぶ
9:10 AM
最適化的には定数伝搬による分岐削除ができてれば、直接Builtin.int_floor_FPIEEE${bits}の呼び出しにできそうなはずだけど
9:10 AM
Doubleの場合もfloorじゃなくてarray[i].round(.down)を使ったら同程度の速度になるみたいです。
まあ結論として
9:11 AM
FloatingPoint.floorは特殊化されたとしても遅い」
9:11 AM
って事になるね。。
9:11 AM
これは共有したほうが良さそう・・・
Avatar
ですね。ベクター扱うライブラリだとFloat/Double用に独自にプロトコル作るほうが良さそうです。
9:11 AM
bugsですかね?
Avatar
omochimetaru 6/3/2019 9:12 AM
悩ましいね。とりあえずbugsは出して、解決案が浮かんだらそれを引用しつつDiscussionかなあ
9:13 AM
自分でfloor2とかをFloatingPointに実装して
9:13 AM
デフォルトではfloorに流しておいて
9:13 AM
FloatDoubleだけは自分で早いやつに向けておけば
9:13 AM
独自プロトコルはいらんのじゃない?
Avatar
それで良さそうですね。
Avatar
omochimetaru 6/3/2019 9:14 AM
あっ
9:14 AM
メソッドじゃねえのかこれ
Avatar
トップレベルですけど内部的に使う分にはまぁ……
Avatar
omochimetaru 6/3/2019 9:15 AM
手元のワークアラウンドは組めそうだけどキレイにいかねえな。
Avatar
https://bugs.swift.org/browse/SR-8746 探してみたらroundedで同じ問題が報告されてました。
9:41 AM
去年の9月って結構放置されてるのでは……
9:42 AM
しかもrintaroさんだ
Avatar
omochimetaru 6/3/2019 9:45 AM
さすりん案件だ
9:48 AM
We were getting that at the time that I implemented these, so this looks like a regression.
9:48 AM
以前は最適化できてたのか。
Avatar
extension FloatingPoint { @inlinable mutating func round_(_ rule: FloatingPointRoundingRule) { if let zelf = self as? Float { switch rule { default: self.round(rule) } } else if let zelf = self as? Double { switch rule { case .towardZero: self = trunc(zelf) as! Self case .down: self = floor(zelf) as! Self case .up: self = ceil(zelf) as! Self case .toNearestOrAwayFromZero: self = Darwin.round(zelf) as! Self default: self.round(rule) } } } こんなかんじに書いただけではまだ遅いですね。 速度が同じくらいになったのでやっぱり分岐が消えてなさそう?
12:53 AM
やっぱprotocol作るしかなさそうですね。
12:56 AM
と思ったけどextension FloatinPoint: Roundableはできないか……
Avatar
@inlinable func floor_<T: FloatingPoint>(_ x: T) -> T { if let x = x as? Float { return floorf(x) as! T } else if let x = x as? Double { return floor(x) as! T } else { return floor(x) } } この粒度なら高速になるのでこのレベルで書くか……
Avatar
func testRoundArray() { var array = [Double](repeating: 1.1, count: 3840*2160*4) measure { // 56ms for i in 0..<array.count { array[i] = floor(array[i]) } XCTAssertEqual(array.last!, 1) } } func testRoundSIMDCast() { var array = [Double](repeating: 1.1, count: 3840*2160*4) measure { // 29ms array.withUnsafeMutableBufferPointer { bp in bp.baseAddress!.withMemoryRebound(to: SIMD4<Double>.self, capacity: bp.count/4) { var p = $0 for _ in 0..<bp.count/4 { p.pointee = floor(p.pointee) p += 1 } } } XCTAssertEqual(array.last!, 1) } } 昨日SILみた段階でそんな感じがしてましたがfloorのsimd最適化はされないみたいですね。 simdにfloorceilだけ定義されててroundその他が無いのも謎……
Avatar
Swift5からSIMDの型が使えるようになったんですね。
Avatar
こんにちは!
👋 2
Avatar
omochimetaru 6/10/2019 8:09 AM
Refer to: Generics Manifesto. I&#39;m not really sure exactly what to discuss here, but right now this is a bare implementation of parameterized extensions. There might be some more that this n...
8:09 AM
Azoy氏がparameterized extension作ってる!
Avatar
Parameterized Extensions Proposal: SE-NNNN Author: Alejandro Alonso Review Manager: TBD Status: Pitching Implementation: apple/swift#25263 Introduction Hello Evolution, this is my first draft at a proposal for Parameterized Extensions. I would greatly appreciate any fee...
Avatar
Azoy氏がピッチを!
Avatar
同じ定義の別記法が産まれて、それがABI非互換ってのはよくないなあ
Avatar
omochimetaru 6/14/2019 1:20 AM
Taking differentiable programming one step closer to Swift Evolution, I wrote a Swift differentiable programming design overview! Everyone is welcome to comment on the Google doc (no login required) and join the open design review tomorrow at 9AM PDT! https://t.co/DuNRtQgH...
1:22 AM
自動微分、本家に入れるモチベあるんですね 機械学習意外で用途なさそうだけどどうなるかなあ
Avatar
The review of SE-0258: Property Wrappers (previously called "Property Delegates") begins now and runs through June 24th, 2019. This is the second review of SE-0258, which was returned for revision subsequent to its first review. Doug Gregor has provided the following list o...
Avatar
omochimetaru 6/17/2019 1:33 AM
特別なプロパティの名前がwrappedValueとwrapperValueに変わってるのは良いですね
Avatar
omochimetaru 6/19/2019 1:12 AM
Differentiable programming is a language feature that we've been incubating for (the official) Swift as part of the Swift for TensorFlow project. After over a year's evolution and experimentation with real-world differentiable programming problems such as machine learning, t...
1:13 AM
本家に自動微分の投稿が!
1:16 AM
機械学習意外で役に立ちそうに無いけど、受け入れられるのかなあ
Avatar
4TFと本家を統合するモチベーションがあるのかな
Avatar
omochimetaru 6/19/2019 4:33 AM
そのへんの言及どうだったかなあ
4:34 AM
ラトナーがdynamicCallableの話したときにはジョーグロフとスラバが結構反対意見も出してたし、
4:35 AM
ラトナーとコアチームでもこのあたりのビジョンは違ってそうだしどう進んでいくんだろうね
Avatar
omochimetaru 6/20/2019 1:07 AM
このスレの書き込みが少ないの、困惑してる人が多いんかな
Avatar
omochimetaru 6/20/2019 1:52 AM
お気持ちを書き込んでみた
Avatar
omochimetaru 6/21/2019 5:34 AM
お返事があって、Swift 4 TFは TensorFlow特化の立ち位置で今後も維持されて、完全には統合されない あくまでその過程で産まれる共通資産だけマージしていく 機械学習以外にもいろいろ活用できるんじゃいとのこと
👀 2
Avatar
できるんじゃいw
Avatar
omochimetaru 6/21/2019 7:27 AM
勢いを感じたので・・・ 原文は適宜確認してや
Avatar
omochimetaru 6/25/2019 5:30 AM
@swift-5.1.5 var dict: [Int: () -> Int] = [:] for i in 0..<3 { dict[i] = { [i] in return i } } for (i, a) in dict { print("\(i) => \(a())") }
Avatar
1 => 1 0 => 0 2 => 2
Avatar
omochimetaru 6/25/2019 5:30 AM
Swiftのescape captureってループカウンタがちゃんとループごとに束縛されてるんだ。
Avatar
これ前に試した気がする。JSかなんかは共通なんよね。
Avatar
omochimetaru 6/25/2019 7:04 AM
はい。Rubyも共通だった気がする。
Avatar
JSの場合ってスコープごとキャプチャされるんだっけ?(他の変数とかもキャプチャしちゃってリークしかねない?)
Avatar
omochimetaru 6/25/2019 7:23 AM
そのような話は聞いた事がないです
Avatar
omochimetaru 6/26/2019 8:40 AM
PropertyWrapperのCodingKeyを調整しようとしても、 enumのcase名に $ が使えないのでできない気がする
Avatar
なるほど、実際にデコードするのはラップされた型だから$が必要なのか
Avatar
omochimetaru 6/26/2019 8:50 AM
@CodingKey("user_name") var userName: String @CodingProxy(Vector3ArrayProxy()) var position: Vector3 とかできたらいいなと思ってたんだけど。
Avatar
Three minor adjustments to the property delegates^Wwrappers implementation to bring it closer to the proposal: Ensure that non-final properties can have attached delegates/wrappers Adjust the name...
9:01 AM
シンセサイズされるコードは$無しを使うようにしてるっぽい
Avatar
omochimetaru 6/26/2019 9:02 AM
おお。
9:02 AM
XcodeBeta2で試してた。
9:03 AM
そうするとキー名の変更はCodingKeysでできるから、Proxyは作り込めばできそうだな
Avatar
@CodingKey難しく無いですか?
Avatar
omochimetaru 6/26/2019 9:06 AM
そっちは無理だと思う
9:06 AM
キー名変更はenum CodingKeysでコレまで通りやるしかない
Avatar
悲しい
Avatar
omochimetaru 6/26/2019 9:08 AM
パッチしたいだけでも全部書かないといけないのがな。
👉 1
Avatar
This has already been fixed in the compiler to align with the proposal under review, but the changes didn't make it into Xcode 11 beta 1 or 2. Doug
9:54 AM
ちょうど今日話題に出てましたね
Avatar
omochimetaru 6/26/2019 9:54 AM
あっ、ほんとだ
Avatar
おぉタイムリーだ
Avatar
omochimetaru 6/26/2019 9:55 AM
このスレ長すぎて読むの諦めた
Avatar
omochimetaru 6/26/2019 5:38 PM
@t.ae マージされたね https://github.com/apple/swift/pull/25658
Make default implementation of AdditiveArithmetic.zero @_transparent. Seems it is simply overlooked.
😋 1
Avatar
omochimetaru 6/27/2019 1:18 AM
Implement the upcoming third revision of the property wrappers proposal, which includes the following changes: The private backing storage property is always named with a leading underscore, e.g.,...
1:18 AM
また名前が変わった!?
1:18 AM
>wrapperValue is renamed to projectedValue
Avatar
omochimetaru 6/27/2019 1:23 AM
Changes from the second reviewed version The synthesized storage property is always named with a leading _ and is always private. The wrapperValue property has been renamed to projectedValue to ma...
1:24 AM
wrapperValueでラッパー本体を差し替えるのをやめて ラッパー本体は常にアンスコ名、projectedValueがあると$付きが生える ってなったのかな??
Avatar
omochimetaru 6/27/2019 3:07 AM
てか6.24までのレビューが閉じずにプロポーザル更新されるのアグレッシブだなあ
Avatar
omochimetaru 6/28/2019 4:45 AM
The review of SE-0258: Property Wrappers (previously called "Property Delegates") begins now and runs through July 3rd, 2019. This is the third review of SE-0258. After the first review, the Core Team requested further development of the proposal to address some concerns rai...
4:45 AM
第3回レビュー開始だ
Avatar
omochimetaru 7/3/2019 3:49 AM
Sequential coming to Swift for TensorFlow via function builders :) cc @eaplatanios https://t.co/7Ca0BX71tO
Likes
126
3:50 AM
Function Builderの用例として、ニューラルネットの構造定義に使うの面白いですね。
Avatar
norio_nomura 7/3/2019 11:47 PM
Swift 5.1では、Function Builderはプライベート機能扱いになるらしい。 https://forums.swift.org/t/function-builders/25167/341
This bug will be fixed in the 5.1 release (https://github.com/apple/swift/pull/25944). Note that unfortunately function builders will remain a private feature in 5.1; we'll have to maintain compatibility with existing code that uses the @_functionBuilder attribute, but we ca...
Avatar
omochimetaru 7/4/2019 12:49 AM
あら。
Avatar
omochimetaru 7/4/2019 9:26 AM
The review of SE-0261: Identifiable Protocol begins now and runs through July 12, 2019. The proposal is written by @anandabits and @kylemacomber. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if y...
9:26 AM
SwiftUIのIdentifiable protocolを標準ライブラリに持ってくる提案
Avatar
中身まだ読んでないけど、 ID が Hashable でないといけない制約は強すぎないかな?一般的な DB はハッシュテーブルじゃなくてツリーだし。 Equatable で良さそうな気が。そのあたりのも書いてあるのかな?後で読んでみよう。
Avatar
norio_nomura 7/4/2019 1:18 PM
元がCombineIdentifierで、それをstdlibへ持って来ようという始まりだから、Hashableを外したら意味が無いのでは。 https://developer.apple.com/documentation/combine/combineidentifier
Avatar
omochimetaru 7/5/2019 12:53 AM
proposalには状態のスナップショットを取って差分計算とかするときにIDが欲しい、とかしか書いてないから、Equatableの必要性は書いてあるけど
12:54 AM
Hashableである理由は書いてないように見える
12:56 AM
スレッドで指摘してるレスもまだ無さそう
Avatar
@norio_nomura HashableID を持つ Identifiable が必要であれば、必要な側で Identifiable を継承して作ればよくないですか?標準ライブラリはできるだけ汎用的な方が良いかと。 protocol Identifiable { associatedtype ID: Equatable var id: ID { get } } protocol HashIdentifiable: Identifiable where ID: Hashable {} struct MyID: Equatable { static func ==(lhs: MyID, rhs: MyID) -> Bool { return true } } struct Foo: HashIdentifiable { // Hashable でないので Error var id: MyID }
Avatar
norio_nomura 7/5/2019 3:00 AM
equality と identity の違いは何か?の話になりそう。 (edited)
Avatar
でも Hashable でも identity を equality に任せるわけですよね?
Avatar
norio_nomura 7/5/2019 3:08 AM
あいや、関係ないか。
Avatar
Why must ID be Hashable? I think Equatable is enough for identification. DBs often use trees for indices instead of hash tables. Don't we want to make ID Comparable instead of Hashable in such cases? Even if ID is just Equatable in the standard library, we can make ID Hashabl...
Avatar
norio_nomura 7/5/2019 3:18 AM
Hashableが無い方は、想定されるユーザーがいるのですかね?
Avatar
うーん、具体例は出せないですが、僕は標準に入れるからには極力最小限にしておきたいなという気持ちがありますね。 Java の ObjecthashCodeequals 持ってたのとか今となっては失敗ですよね?
Avatar
omochimetaru 7/5/2019 3:34 AM
collectionのdiffはT: Equatableだし。
Avatar
Java の Object.hashCode についても追記しといた。
Avatar
SwiftUI では↓を宣言しなおせばいいと思うんですよね。 protocol Identifiable: Swift.Identifiable where ID: Hashable {}
3:40 AM
使うときに名前衝突が面倒かな?
Avatar
omochimetaru 7/5/2019 3:40 AM
import SwiftUI struct User : Identifiable { ... }
3:40 AM
こうしたときは SwiftUI.Identifiable > Swift.Identifiable で解決するはず
Avatar
それなら問題ないね。
Avatar
omochimetaru 7/5/2019 3:41 AM
Swift.Resultが入った時にantitypical/Resultとの絡みでそうなった
Avatar
お、そうなってなかった気がしてたけど、最近なったのか。
Avatar
omochimetaru 7/5/2019 3:41 AM
5.0のところで整った。
Avatar
素晴らしい。
Avatar
Kishikawa Katsumi 7/5/2019 4:02 AM
実用を考えるとHashableでいいと思うんですよね。
4:04 AM
Identifiableが必要なケースはそれなりのボリュームを処理したいということだから、EquatableのショートカットとしてのHashableが普通は必要になるはず。
Avatar
omochimetaru 7/5/2019 4:05 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
4:05 AM
プロポーザルのMotivationセクションには
4:05 AM
配列のdiffを取ってListViewを更新する話しか書いてないから
4:05 AM
それでいくとEquatableで十分になってしまう。
Avatar
Kishikawa Katsumi 7/5/2019 4:06 AM
ListViewを更新するのEquatable だけよりHashableの方が断然効率いいですよね。
Avatar
omochimetaru 7/5/2019 4:07 AM
いえ、MayerのDiffアルゴリズムの場合、辞書を使って加速する部分はないです http://blog.robertelder.org/diff-algorithm/
Avatar
Kishikawa Katsumi 7/5/2019 4:08 AM
いや、==とhashValueの呼び出しは普通hashValueの方が速い、というのが言いたかったことです。 (edited)
4:09 AM
というかHashableというのはそうすべきものなので。
Avatar
omochimetaru 7/5/2019 4:12 AM
あれ?それって正しいですかね?
4:12 AM
ハッシュ値を求めるためにはそのデータの全ビットをスキャンしないといけなくて、 さらに掛け算や足し算をすることになるので
Avatar
Kishikawa Katsumi 7/5/2019 4:12 AM
標準に入れるからには極力最小限にしておきたい
これもわかるんですけど、普通に使って遅かったりしない、というのも標準には重要かなと。
Avatar
omochimetaru 7/5/2019 4:12 AM
A == B を直接比較するのと、 AとBのハッシュ値をそれぞれ求めてからそれを比較するのって、
4:12 AM
後者のほうが遅いような気がします。
4:13 AM
ハッシュ値が意味があるのは、ハッシュテーブルに入れて検索する時にO(1)で見つけられる場合だけなのでは。
4:15 AM
コレクション同士の場合は要素のハッシュ値をキャッシュできるから比較がなんども発生する場合には高速化するのかな?
4:16 AM
You can expect faster execution when the collections share many common elements, or if Element conforms to Hashable.
4:16 AM
ちょうど書いてあった。
Avatar
Kishikawa Katsumi 7/5/2019 4:16 AM
ちょっと私も書いてて自信無くなってきました。
Avatar
omochimetaru 7/5/2019 4:17 AM
func difference<C>(from other: C) -> CollectionDifference<Self.Element> where C : BidirectionalCollection, Self.Element == C.Element Available when Element conforms to Equatable. BidirectionalCollection.differenceは、要素をEquatableを要求するけど、Hashableのときは加速するらしい。
Avatar
Kishikawa Katsumi 7/5/2019 4:17 AM
これからオフィスに向かうのでその道すがら考えを整理します 😇
Avatar
norio_nomura 7/5/2019 4:18 AM
Hashableのときは加速するらしい。
素晴らしい。
4:20 AM
特に実装がそうなってない・・・ (edited)
4:23 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
norio_nomura 7/5/2019 4:27 AM
えー…
🤔 1
Avatar
hashは衝突していいので、「全ビットをスキャン」しなくても雑なスキャンで高速化はあり得るんじゃないでしょうか。
Avatar
omochimetaru 7/5/2019 5:28 AM
全ビットを影響させて衝突を防ぐのがハッシュの実装のベストプラクティスのはずです
5:28 AM
そこで手を抜くと逆に衝突確率があがり、辞書のパフォーマンスとしてみると赤字になるんだと思います
Avatar
norio_nomura 7/5/2019 5:42 AM
Hashableを使った func ==func != もstdlibには無いみたい。 (edited)
5:43 AM
Diffing.swiftで唯一Hashableが影響しえた部分がfunc ==だったから、さっき見直してみた。
Avatar
omochimetaru 7/5/2019 5:44 AM
ところで、「全ビットを使わないでハッシュを高速化」に関しても、==の途中で異なるフィールドが出てくれば、そこで中断できるので、それと同じ事だと思います
5:45 AM
それと、ハッシュは「異なる」ことしかわからないので、「等しい場合」については再計算が必要になるので高くつく場合もあります。
Avatar
norio_nomura 7/5/2019 5:54 AM
Stringのハッシュとかは一部しか計算に使っていませんでしたが、Hashableが変わってからは調べてないな。
Avatar
Kishikawa Katsumi 7/5/2019 6:36 AM
私は完全に勘違いしていました。hashは==のショートカットとして常に使える気がしていましたが、そんなことはないですね。 なので上で書いた私の意見は全部間違いです 🙇
6:36 AM
と、いうのをたった今ちょっとコード書いて検証しました 😓
Avatar
norio_nomura 7/5/2019 7:24 AM
Objective-Cの時は全てにhashがあって、NSArrayとかは要素数を返したりしたから、hash比較で!=を得るのが速い場面も無くはなかった。 @swift-5.0.3 import Foundation let a: NSArray = [1, 2, 3] print(a.hash)
Avatar
swift50 BOT 7/5/2019 7:24 AM
3
Avatar
objcの頃は遅い-isEqual:を避けるためにまず-hashを使うというのがあったので-hashはぶつかってもいいから高速にと思ってたんだけど、別に-hashを速くしろとは書いてないみたい
7:50 AM
中身が同じなら別のインスタンスでも同じとみなすクラスでもない限り-hash(と-isEqual:)は書かなかったけど
Avatar
omochimetaru 7/5/2019 9:12 AM
Objective-Cの時は全てにhashがあって、NSArrayとかは要素数を返したりしたから、
オワー!なんだこりゃ・・・
Avatar
たしかに < 中断できる (特にイミュータブルクラスとかで)ハッシュ値をキャッシュしたときとかは速くなりそうだけど大分限定的だなぁ。
Avatar
The third review of SE-0258 has concluded. There was a lot more great discussion in this review, and while there were some questions and reservations, overall the community expressed strong support for accepting the proposal. The Core Team agrees and has decided to accept S...
Avatar
omochimetaru 7/11/2019 1:33 AM
ついに決着
Avatar
ORT 使ったら existential や type erasure を使わずに heterogeneous なコレクションを実現できそうな気がしてるんだけどどうでしょう(↓みたいな感じで)?ただし、現状ではループして取り出す方法がないし、これをうまく扱うには道具が足りてなさそう。 import SwiftUI protocol ViewSequence { associatedtype Element: View associatedtype Next: ViewSequence var element: Element { get } var next: Next { get } } extension Never: ViewSequence { var element: Never { fatalError() } var next: Never { fatalError() } } struct ViewSequenceNode<Element: View, Next: ViewSequence>: ViewSequence { let element: Element var next: Next { if let next = _next { return next } else { fatalError() } } fileprivate let _next: Next? init(element: Element, next: Next) { self.element = element self._next = next } } extension ViewSequenceNode where Next == Never { init(element: Element) { self.element = element self._next = nil } } func foo() -> some ViewSequence { return ViewSequenceNode( element: Text("Hello"), next: ViewSequenceNode( element: HStack { Text("World") }, next: ViewSequenceNode( element: VStack { Text("!") } ) ) ) } let views = foo() print(views.element) print(views.next.element) print(views.next.next.element)
Avatar
omochimetaru 7/11/2019 7:05 AM
some ViewSequenceの時点で型情報が見えなくなってるので、リストの長さに関して型安全にならないと思います
Avatar
これは sequence だから count はないけど、 count を付けること自体はできるんじゃない?
Avatar
omochimetaru 7/11/2019 7:10 AM
動的なcountはできると思いますけど、その場合ユーザーから見て、 (edited)
7:11 AM
ViewSequenceNodeが型パラメータNextを持たずに、var nextをViewSequenceのerasureで保持した場合と何が変わっているんです?
Avatar
type erasure や existential によるパフォーマンスロスを削減できる。
Avatar
omochimetaru 7/11/2019 7:12 AM
あ〜そうか、たしかに。
Avatar
↑が有用だと主張してるわけじゃないけど、 SwiftUI は ORT でパフォーマンスロスが・・・とか言ってるけどコレクションが結局 erasure ( AnyView )でロスしてるよなと思って、 SwiftUI がジェネリック地獄を ORT で解消してるのを参考に似たようなことができないかなと。
7:14 AM
ただ、ループで回そうとしても element が一つずつ型が変わるから、専用の構文でも導入しないと回せないと思うんよね。 (edited)
Avatar
omochimetaru 7/11/2019 7:14 AM
ループで回すところに関してはOpaqueになった時点で、静的に次の要素の型がわからないから、AnyViewとかでeraseすることになりそうですね
Avatar
それを erase せずに element を some View として扱ってアンロールしてくれる専用構文が必要そう。
7:16 AM
型から要素数がわかるからコンパイラがアンロールできるはず。
7:17 AM
しかも、 element を some View 扱いすれば共通のコードがアンロールされた個々の箇所ではちゃんと働きそう。
7:18 AM
heterogeneous sequence を表すプロトコルか何かを導入して、それを for 文に突っ込んだときは↑のようにアンロールとかいう挙動をコンパイラに実装すればできそう。
7:20 AM
array literal も拡張しないと ExpressibleByArrayLiteral を経由するときに erase されちゃうな。
Avatar
omochimetaru 7/11/2019 7:24 AM
some ViewSequence<.Element == Int> とかが書けるようになったとして、 some ViewSequence.elementsome View で良さそうですね
Avatar
some HeterogeneousSequence<.Element: View> とかで、 Elementsome View かなぁ。
7:26 AM
今は ORT に <.Element: ...> が書けないかなら : View 縛りで ViewSequence として試してみた。
Avatar
omochimetaru 7/11/2019 7:28 AM
protocol HeterogeneousSequence { associatedtype Element } に対して some HeterogeneousSequence<.Element : View> と制約するなら seq.elementsome View になりそうですね、理論的には。
Avatar
コレクションを Opaque Type の世界に持ってこれたら新しそうな気がするんだよなぁ。
7:29 AM
ただ、 some View になってもループ回るごとに実の型は違うからそのまま扱うと結局 existential になっちゃうから、コンパイラがアンロールしてくれないといけないんよね。
Avatar
omochimetaru 7/11/2019 7:31 AM
そうですね ループの周回ごとに違うコードが要る (edited)
Avatar
あー、でもイテレートはそれでよくても、作る方とか無理かな・・・
7:33 AM
いや、そもそも無理なのか、ループしながら要素を追加してコレクション作り上げようとしても
7:34 AM
ループ回るごとに完成形の型が変わっちゃうから、それを格納する変数を記述できない。
Avatar
omochimetaru 7/11/2019 7:34 AM
現状だとそういうイテレーターをfor文に適合するように記述する規格が無いですね。
7:34 AM
勝手な func forEach(f)とかならできそう。 (edited)
Avatar
var collection: ??? = [] for foo in foos { collection = collection.appended(foo) } みたいなのができない。
7:35 AM
??? の部分がループ回るごとに変わる。
7:36 AM
( Rust のシャドーイングみたいに?)型を上書きする仕組みが必要そう。アンロールしながら↑の collection の型をシャドーイングで上書きしていく。 (edited)
7:38 AM
現状だとそういうイテレーターをfor文に適合するように記述する規格が無いですね。
イテレートに関しては、新しい HeterogeneousSequence プロトコルとかを導入して、それに適合した型が for に渡された場合はコンパイラがアンロールっていう挙動に改造すればいけると思うんよね。
(edited)
Avatar
omochimetaru 7/11/2019 7:38 AM
HeterogeneousSequenceを言語仕様で入れちゃうのはありですね
Avatar
組み立てる側はそれだけで済まない変更が必要そうだ。
7:39 AM
任意の N 要素から組み立てるコードの場合。
Avatar
コンパイル時に型が決められないから動的に組み立てるのはダメだな。
9:39 AM
それなら、すべての要素が同じ制約を満たしていて、それを some Foo としてイテレートできて、 for に渡すとアンロールしてくれるタプルがあれば十分だな。
Avatar
norio_nomura 7/23/2019 1:48 AM
Standard Libraryへ追加する機能をプレビューするパッケージを作ろうというpitch https://forums.swift.org/t/pitch-standard-library-preview-package/27202
Hi Swift community, Here's a first draft of a proposal we've been working on that should help us work in our new, post-ABI stability, post-Xcode package manager integration world. PR for the proposal can be found here. Standard Library Preview Package Authors: Ben Cohen, M...
Avatar
omochimetaru 7/23/2019 3:58 AM
ああそうか、Standard Libraryの変更は、ツールチェインごと切り替えないといけないから試しづらかったけど、
3:58 AM
ツールチェインはそのままでStdlibだけ新しいのに試しに切り替える、というのがやりやすくなるのか。
4:02 AM
Take SE-0199 4 (the introduction of toggle) for example. It was accepted 4 almost 6 month before Swift 5 was released.
コレな
Avatar
norio_nomura 7/26/2019 3:17 AM
今更だけど、static let …はonceなチェックが毎回入るけど、static var … { get }だと入らない。onceチェックのコストより新規インスタンス生成のコストが低く、ポインタでの参照が不要の場合、後者を選んだ方が良いのか。
3:18 AM
onceチェックのコストってどれくらいだろう
Avatar
omochimetaru 7/26/2019 3:32 AM
それ知りたい
Avatar
norio_nomura 7/26/2019 3:34 AM
static let …の方は、コンパイル時に評価してしまえる場合、オプティマイザがonceチェックとかすっ飛ばして即値を持ってきたりする。
3:35 AM
なので、static letstatic var { get }の速度差は、デバッグビルドでのパフォーマンスにしか影響しない場合もある。 (edited)
Avatar
omochimetaru 7/26/2019 3:36 AM
constexprが入れば、その最適化を静的に保証できるので楽しみ
Avatar
norio_nomura 7/26/2019 4:02 AM
-emit-assemblyを見ると、onceチェック2回目以降のコストは無視して構わない感じだけど、初回コストが大きいかも。
Avatar
omochimetaru 7/26/2019 9:54 AM
2回目以降の初期化済みかどうかスレッドセーフに調べるところはどうかなあ
Avatar
_swift_onceへ渡すトークンの値が-1かどうかチェックしてるだけだった。 cmpq $-1, <token>してje_swift_onceをスキップ。
10:43 AM
.private_extern main.S.letStatic.unsafeMutableAddressor : main.S .globl main.S.letStatic.unsafeMutableAddressor : main.S .p2align 4, 0x90 main.S.letStatic.unsafeMutableAddressor : main.S: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset %rbp, -16 movq %rsp, %rbp .cfi_def_cfa_register %rbp cmpq $-1, _globalinit_33_1A61A3E7348A44FC8FF8726B26BEB4ED_token0(%rip) je LBB7_2 leaq _globalinit_33_1A61A3E7348A44FC8FF8726B26BEB4ED_func0(%rip), %rax leaq _globalinit_33_1A61A3E7348A44FC8FF8726B26BEB4ED_token0(%rip), %rdi movq %rax, %rsi callq _swift_once LBB7_2: leaq static main.S.letStatic : main.S(%rip), %rax popq %rbp retq .cfi_endproc
Avatar
omochimetaru 7/29/2019 2:01 AM
最初にもし2スレッドが突入した場合はその先の_swift_onceで同期をとるから大丈夫で、 それ以降は同期無しでスキップできるのか
Avatar
norio_nomura 7/30/2019 9:05 AM
あれ?iOSのJSONEncoderっていつからUInt単体でエンコードできる様になったの? (edited)
Avatar
beta 5からJSONEncoderがこのオプションをJSONSerializationへ渡す様になったぽい。
Avatar
なんかXcode11b5で、(Never)->Tなクロージャの定義がコンパイルエラーになるようになった気がする。
4:26 AM
Will never be executed がerrorになってるから、これはwarningかどうかフラグで切り替えるようになったのかな
4:28 AM
↑RACが SWIFT_TREAT_WARNINGS_AS_ERRORS=YES;を入れている+新しいWarningが追加されたから、っぽかった。
Avatar
@swift-5.0.3 let r1: Range<Int> = 1..<10 let r2 = r1.dropFirst(1) print(type(of: r2))
Avatar
swift50 BOT 8/3/2019 3:47 AM
Range<Int>
Avatar
@swift-5.0.3 let r1: ClosedRange<Int> = 1...10 let r2 = r1.dropFirst(1) print(type(of: r2))
Avatar
swift50 BOT 8/3/2019 3:47 AM
Slice<ClosedRange<Int>>
👀 1
Avatar
ClosedRangeSubSequenceClosedRange でないのは ClosedRange だと空のレンジを表現できないから? (edited)
Avatar
omochimetaru 8/3/2019 3:57 AM
ええなんだこれ
Avatar
空の ClosedRange を作れなくて↓の r2 のようなケースが表現できないのかなと。 @swift-5.0.3 let r1 = 1...1 let r2 = r1.dropFirst(1) print(Array(r2))
Avatar
swift50 BOT 8/3/2019 4:11 AM
[]
Avatar
@swift-5.0.3 typealias OptString = String? struct User { var name: String? var email: OptString init(name: String) { self.name = name } } let user = User(name: "kagemiku")
Avatar
swift50 BOT 8/6/2019 1:52 AM
exit status: 1 with stderr:<stdin>:9:5: error: return from initializer without initializing all stored properties } ^ <stdin>:5:9: note: 'self.email' not initialized var email: OptString ^
Avatar
@swift-4.2.4 typealias OptString = String? struct User { var name: String? var email: OptString init(name: String) { self.name = name } } let user = User(name: "kagemiku")
Avatar
swift42 BOT 8/6/2019 1:53 AM
no output
Avatar
↑のように、swift5で コード例のような イニシャライズができなくなってるっぽいです
Avatar
omochimetaru 8/6/2019 2:05 AM
Optionalの自動初期値nilがtypealiasの場合に効かない挙動に変わった?
2:06 AM
意図された仕様変更なのか、実装上で挙動が変わってしまったのか、どっちだろう・・
2:09 AM
@swift-5.0.3 @swift-4.2.4 var a: Int? print(a) var b: Optional<Int> print(b)
Avatar
swift50 BOT 8/6/2019 2:09 AM
exit status: 1 with stderr:<stdin>:2:7: warning: expression implicitly coerced from 'Int?' to 'Any' print(a) ^ <stdin>:2:7: note: provide a default value to avoid this warning print(a) ^ ?? <#default value#> <stdin>:2:7: note: force-unwrap the value to avoid this warning print(a) ^ ! <stdin>:2:7: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(a) ^ as Any <stdin>:4:7: warning: expression implicitly coerced from 'Optional<Int>' to 'Any' print(b) ^ <stdin>:4:7: note: provide a default value to avoid this warning print(b) ^ ?? <#default value#> <stdin>:4:7: note: force-unwrap the value to avoid this warning print(b) ^ ! <stdin>:4:7: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(b) ^ as Any <stdin>:4:7: error: variable 'b' used before being initialized print(b) ^ <stdin>:3:5: note: variable defined here var b: Optional<Int> ^
Avatar
swift42 BOT 8/6/2019 2:09 AM
nil nilstderr:<stdin>:2:7: warning: expression implicitly coerced from 'Int?' to 'Any' print(a) ^ <stdin>:2:7: note: provide a default value to avoid this warning print(a) ^ ?? <#default value#> <stdin>:2:7: note: force-unwrap the value to avoid this warning print(a) ^ ! <stdin>:2:7: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(a) ^ as Any <stdin>:4:7: warning: expression implicitly coerced from 'Optional<Int>' to 'Any' print(b) ^ <stdin>:4:7: note: provide a default value to avoid this warning print(b) ^ ?? <#default value#> <stdin>:4:7: note: force-unwrap the value to avoid this warning print(b) ^ ! <stdin>:4:7: note: explicitly cast to 'Any' with 'as Any' to silence this warning print(b) ^ as Any
Avatar
omochimetaru 8/6/2019 2:10 AM
Int?は自動初期化だけどOptional<Int>はそうではないようだ。
2:10 AM
↑ここで見た
2:10 AM
ただこれも5.0からの挙動だ。
Avatar
typealias 起因というよりは、Optionalの実装起因、という感じですかね
4:11 AM
過去に報告されていて、Slavaがこれはリグレッションじゃなくて4.2→5.0での変更ですと答えているので、仕様っぽいです。
Avatar
なんと…仕様とは ありがとうございます
Avatar
omochimetaru 8/6/2019 4:33 AM
ソース互換性が壊れるけど、Evolutionプロセスにこんなのあったっけ・・・
Avatar
norio_nomura 8/6/2019 5:47 AM
@_hasInitialValue @swift-5.0.3 -frontend -emit-sil var a: Int? var b: Optional<Int>
Avatar
swift50 BOT 8/6/2019 5:47 AM
sil_stage canonical import Builtin import Swift import SwiftShims @_hasStorage @_hasInitialValue var a: Int? { get set } @_hasStorage var b: Optional<Int> { get set } // a sil_global hidden @$s4main1aSiSgvp : $Optional<Int> // b sil_global hidden @$s4main1bSiSgvp : $Optional<Int> // main sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): alloc_global @$s4main1aSiSgvp // id: %2 %3 = global_addr @$s4main1aSiSgvp : $*Optional<Int> // user: %6 %4 = metatype $@thin Optional<Int>.Type %5 = enum $Optional<Int>, #Optional.none!enumelt // user: %6 store %5 to %3 : $*Optional<Int> // id: %6 alloc_global @$s4main1bSiSgvp // id: %7 %8 = global_addr @$s4main1bSiSgvp : $*Optional<Int> %9 = integer_literal $Builtin.Int32, 0 // user: %10 %10 = struct $Int32 (%9 : $Builtin.Int32) // user: %11 return %10 : $Int32 // id: %11 } // end sil function 'main'
Avatar
norio_nomura 8/6/2019 5:51 AM
Int?の方は@_hasInitialValueってのが付くのね。
Avatar
omochimetaru 8/6/2019 5:54 AM
ほー
Avatar
norio_nomura 8/6/2019 6:44 AM
このPRに、Optional<Int>Int?の挙動が違う理由が書かれてるhttps://github.com/apple/swift/pull/12770 (edited)
In Swift 4, properties declared with a sugared Optional type, like Int?, have a default value of nil. This can be observed in two ways: Classes and structs get an implicit no-argument initializer ...
Avatar
omochimetaru 8/6/2019 6:52 AM
A recent refactoring cleaned up some of the mess in this area, but accidentally broke source compatibility with code that relied on the broken Optional case.
6:53 AM
最近のリファクタリングで間違ってソース互換性を壊しちゃったから-swift-version 4で互換する実装をしたよ、が12770?
Avatar
norio_nomura 8/6/2019 7:01 AM
シンタックスシュガーを使っていないオプショナルが、Swift 4でデフォルト値を持っていた挙動はバグだったとも、コメントからは読める。 // Note: Swift 4 had a bug where properties with a desugared optional // type like Optional<Int> had a half-way behavior where sometimes // they behave like they are default initialized, and sometimes not. // // In Swift 5 mode, use the right condition here, and only default // initialize properties with a sugared Optional type. // // (The restriction to sugared types only comes because we don't have // the iterative declaration checker yet; so in general, we cannot // look at the type of a property at all, and can only look at the // TypeRepr, because we haven't validated the property yet.) (edited)
7:04 AM
いや、違うな。
7:07 AM
Swift4でOptionalを持つ型のイニシャライザがバグってたから直したけど、その影響でsugared typeのOptionalだけ初期値を持てる様になってしまった、みたいな状態なのかな。 (edited)
Avatar
これは謎な挙動だ
Avatar
omochimetaru 8/7/2019 1:48 AM
Swift works great as an infinitely hackable syntactic interface to semantics that are defined by the compiler underneath it. The two options today are LLVM (there&#39;s a running joke that Swif...
1:49 AM
Swift for TFのユージンさんがなんかやばいの作ってる
1:50 AM
Scalaのマクロ機能について活躍してる人らしい
1:51 AM
This is a public document Swift as syntactic sugar for MLIR Author: Eugene Burmako Last Updated: 8/6/2019 History 2019/8/6 Initial public version of the document that describes five designs for metaprogramming MLIR in Swift. None of the designs have been implemented - we are ...
1:52 AM
多分この文書ではMLIRのコードをSwiftにembedする上でどういう言語インターフェースがありえるかを議論していて、
1:53 AM
このPRではその一つの実例として #quote(funcName) とすることで関数のSwiftASTを返す言語機能を作った?
Avatar
Deleted User 8/7/2019 3:47 AM
😅
3:48 AM
S4TFもMLIRもstableじゃないのに良くやるわ…
Avatar
omochimetaru 8/7/2019 3:51 AM
その文字列リテラル方式のところで何の話をしたいのかわかったw
Avatar
Deleted User 8/7/2019 3:59 AM
これ例えばscala(string)でスカラ使えるとかですか?
Avatar
omochimetaru 8/7/2019 4:00 AM
Scalaだとコード全体が無いとコンパイルできないので実用性が無さそうですが
4:00 AM
scalaのREPL環境を実行時に用意して、scala("...") のたびにそこに投入していくみたいな実装なら動作しそうですね
4:04 AM
ただこれ、MLIRを実行時に構成してもあんまりうれしくないような。
4:04 AM
コンパイル時計算と組み合わせて、埋め込んだMLIRをコンパイルしておかないと、
4:04 AM
Swift書いてるのに静的言語環境じゃなくなりそうな
Avatar
Deleted User 8/7/2019 4:06 AM
mlirをmachine learningの目的で使うなら嬉しさがなさそう、というかs4tfを使った方が良さそうだしあまりゴールが見えない
Avatar
Sequence.Element って何のために追加されたんでしたっけ?元々 Sequence.Iterator.Element で良かったと思うんですが、それだと面倒だから? Proposal ありますっけ? ↓によると Xcode 9 ( Swift 4 )で追加されてそうですが、 Proposal 一覧を "element" で検索してもひっかからず。リファレンスの表記上の問題で "Xcode 9.0+" になってるだけで、もっと前に追加されましたっけ? https://developer.apple.com/documentation/swift/sequence/2908099-element
Avatar
omochimetaru 8/10/2019 7:47 AM
…nt to ArrayLiteralElement (#8990)
  • Give Sequence a top-level Element, constrain Iterator to match
  • Remove many instances of Iterator.
  • Fixed various hard-coded tests
  • XFAIL a few tes...
7:47 AM
このコミットで追加されていますね
7:48 AM
This change will allow generic algorithms to refer to Sequence.Element instead of Sequence.Iterator.Element. The PR is big but the vast bulk of the changes are removal of Iterator. from numerous li...
7:48 AM
And change ExpressibleByArrayLiteral.Element to ArrayLiteralElement (#8990) 4.0 merge of #8990
7:49 AM
4.0からっぽい。
Avatar
これを見る限り Proposal を経なかった感じかなぁ。
Avatar
omochimetaru 8/10/2019 7:51 AM
Evolutionにも見当たらないですね
Avatar
Additive かもしれないけど、 Proposal 経ないにしては結構大きな変更じゃない? Sequence とか基幹となるプロトコルだし。
7:55 AM
あと、この Element って associatedtype じゃないといけないんだっけ? typealias Element = Iterator.Element ではダメだった?
Avatar
omochimetaru 8/10/2019 7:57 AM
エイリアスだから無断で追加したのかと思ってたけど
7:57 AM
意味変わるのかな?
7:57 AM
僕もエイリアスだと思ってたけど制約つきのassoctypeなんですねえ
Avatar
Generalized Existential を見越したら、 typealias は指定できるパラメータの対象にならない? Sequence<.Element == Int> とかのときに。
8:03 AM
型パラの制約には typealias でも指定できるんだから、 Generalized Existential でも同じなのが自然か。 @swift-5.0.3 protocol P1 { associatedtype X func f1() -> X } protocol P2 { associatedtype Y: P1 //associatedtype X where X == Y.X typealias X = Y.X func f2() -> Y } func foo<P: P2>(_ p: P) where P.X == Int {}
Avatar
no output
Avatar
OrderedSetは何故Swiftで無くなってしまったんだろう🤔 (正確にはNS接頭辞削除祭りから何故除外されてしまったのか…)
Avatar
Kishikawa Katsumi 8/15/2019 8:28 AM
標準ライブラリのデータ構造、もう少し充実させてほしいですよね。
Avatar
omochimetaru 8/15/2019 9:12 AM
binarySearchはまあまあ使うので標準に欲しい
Avatar
Kishikawa Katsumi 8/15/2019 12:09 PM
NSArrayにはあるんですよね。Arrayに付けてほしい。
Avatar
Hello, I'm back with yet another formulation of offset-based indexing and slicing. This builds on all the discussions from Pitch: Offsetting Indices and Relative Ranges and prior. The swift-evolution PR can be found here. Offset Indexing and Slicing Proposal: SE-NNNN Author...
12:25 AM
インデックスめんどくさい問題の新提案
12:26 AM
これは良いアイデアだと思う
Avatar
omochimetaru 8/30/2019 4:28 AM
Swift5.1で
4:29 AM
enum E : Int { case a; case b } switch E(rawValue: 0) { case .a: print("a") case .b: print("b") case .none: print("none") }
4:29 AM
って感じで、enumのOptionalに対して.someをつけずに網羅的にswitch-caseが書けるようになってるの便利なんだけど
4:29 AM
proposalあったっけ。
Avatar
That's a good idea. It ought to comple as well. That's a bug. Thanks for raising these issues! If you have a moment, both of them are worth filing on bugs.swift.org, if you haven't already.
4:53 AM
バグ扱いだったみたいですね
Avatar
omochimetaru 8/30/2019 5:22 AM
なるほどw
Avatar
Xcodeのリリースノートにも明記されてるのにバグなのか...
Avatar
リリースノート側では機能改良なの?
10:29 AM
.someつけずに書けるのはこれのことやんね?
10:29 AM
SwiftのNew Featuresとして書いてあるね
Avatar
それですw
Avatar
Kishikawa Katsumi 8/30/2019 10:33 AM
新機能だと思ってた
Avatar
プロポーザルこれか?チケットに紐付いてた https://forums.swift.org/t/matching-optionals-in-a-switch-statement/12905
I have two questions about matching optionals in a switch statement. Apparently an Int? can be matched against non-optional integer literals or non-optional integer expressions: let x: Int? = 1 switch x { case 1: print("one") case 1?: print("one?") case 1+2: print("one+two...
10:34 AM
いや承認プロセスとか無さそうだし違うのか
Avatar
そのスレでジョーグロフが
It ought to comple as well. That's a bug.
10:35 AM
スレ自体はIntのときとenumのときで挙動違くない?って指摘
10:35 AM
挙動を同じにすると最終的に網羅チェックがついてくる、みたいな。
Avatar
RobertさんがThat's not a bugと言って、Joe GroffがThat's a bugと言ってカオスだw
Avatar
ほんとだwロバートってコダフィーさんか
Avatar
そうそう。時間ある時にあとで読んでみる
Avatar
omochimetaru 9/3/2019 4:51 PM
Hi Andy, your work looks really interesting, but there were no more updates since March. Could you tell us what's the current status? Ps: I'd like to present also this very interesting paper: Swift for Embedded Systems
4:52 PM
STM32マイコンでSwift動かした修士論文?がシェアされてる
4:52 PM
9月からマージを計画してるらしい
Avatar
最高じゃんw
4:53 PM
大学の授業これでやりたかった
Avatar
omochimetaru 9/3/2019 4:57 PM
結論のとこにコードサイズが問題って書いてある
Avatar
omochimetaru 9/14/2019 7:59 AM
Hi Swift community, We have completed a comprehensive proposal for the differentiable programming feature we’ve been incubating over the last 1.5 years. We’ve gone over many iterations on the feature design, and have partially completed the implementation. Now we are rea...
7:59 AM
見逃してた 微分機能のプロポーザル来てた
7:59 AM
メガって付いてるw
Avatar
@swift-5.1.5 let t = Int.self let a: [t] = [2, 3, 5] print(a.reduce(0, +)) // 10
Avatar
exit status: 1 with stderr:<stdin>:2:9: error: use of undeclared type 't' let a: [t] = [2, 3, 5] ^
Avatar
↑を REPL で 1 行ずつ実行するとできたんだけど、そういうものだっけ?
7:46 PM
Avatar
-frontend -replだとエラーになるね。 $ swift -frontend -repl -sdk $(xcrun --show-sdk-path --sdk macosx) *** You are running Swift's integrated REPL, *** *** intended for compiler and stdlib *** *** development and testing purposes only. *** *** The full REPL is built as part of LLDB. *** *** Type ':help' for assistance. *** (swift) let t = Int.self // t : Int.Type = Swift.Int (swift) let a: [t] = [2, 3, 5] <REPL Input>:1:9: error: use of undeclared type 't' let a: [t] = [2, 3, 5] ^ (swift)
Avatar
Kishikawa Katsumi 9/23/2019 1:06 PM
iPlaygroundでDifferential Programmingの話をした人は、Mega proposalは100%マージされるって言ってた。
Avatar
omochimetaru 9/23/2019 4:42 PM
スレッド見ると、「素晴らしい機能だとは思うけど、普段使わない機能がコンパイラに組み込まれて、今後いろんな改修のたびにこの部分もメンテナンスするコストが上がっちゃうのが大丈夫ならいいんじゃない、」みたいなコメントが多い感じがする
4:43 PM
でもそもそもこれは、Swiftのユーザー領域を増やすための機能って側面が強いから、現在のユーザーが集まって話し合ってるフォーラムで意見を聞いても噛み合わないので、
4:43 PM
仕組みとしてフォーラムがうまく機能してないなと自分は感じた。
4:44 PM
まあコアチームはそのへんわかって、設計まで踏み込んだツッコミとか以外は無視すると思うから実際マージする方向に進むんじゃないかと予想している
Avatar
Kishikawa Katsumi 9/24/2019 1:34 AM
既存の挙動をまったく変更しないというのと、もうすでにいくつかの実装はマージされてるし、って感じみたいですね。
Avatar
omochimetaru 9/24/2019 6:52 AM
The review of SE-0264 — Standard Library Preview Package begins now and runs through Sept 30, 2019 The proposal is written by @ben_cohen, @moiseev, and @nnnnnnnn. Reviews are an important part of the Swift evolution process. All review feedback should be either on this fo...
6:53 AM
標準ライブラリのベータ版パッケージSwiftPreviewを導入する提案!
Avatar
A simple solution to the ambiguity problem of multiple ‘trailing’ closures is to simply require that they start on the same line as the preceding closure, after the }. e.g.: // This is a single call to when(::otherwise:) when (2 < 3) { doSomething() } otherwise { do S...
12:11 PM
2つ目のクロージャ引数も丸括弧の外に出したい提案
Avatar
func when<T>(condition: @autoclosure () -> Bool, then trueBranch: () -> T, `else` falseBranch: () -> T) -> T { if condition() { return trueBranch() } else { return falseBranch() } } let a = when (2 < 3) { 3 } else { 4 }
Avatar
なるほど、そこにラベルが来るのか
Avatar
パーサー的につらそうって意見があって
12:20 PM
requests.get("/user?ID=12345") { response in let user = response.args["user"] ... } catch: { print("Something went wrong") } finally: { // Always execute };
12:20 PM
↑こんな案も出てる
12:20 PM
これでもラベルと曖昧だよなあ。
12:21 PM
trailing closureとsecond labelの間に何か特定のトークンを置くような規則じゃないとつらそう
Avatar
ラベル名だけで区切るのはパーサ辛そうですね
Avatar
,置くのが妥当ではなかろうか
Avatar
omochimetaru 9/27/2019 1:47 PM
理屈はそうだけど、見た目に千切れた感じにならない?
Avatar
例えば Dictionary 的な機能を持つ protocol を定義するとして、 mapValues を protocol level で書く(Value 型を変える)ということはできないのでしょうか? struct Dictionary では: func mapValues<T>(_ transform: (Value) throws -> T) rethrows -> [Key : T] が定義されていますが,これを protocol DictionaryProtocol { associatedtype Key: Hashable associatedtype Value func mapValues<T>(_ transform: (Value) throws -> T) rethrows -> Self (where Value == T) } のようなことをしたい…🙄(もしそれがあるのであれば Sequence の map 型も [T] と specialize された形になってないはずなので,やはり無理なのでしょうか) (edited)
Avatar
これはHigherKindedTypeと呼ばれる機能が相当しますね。そしてSwiftにはないです。
Avatar
ふーむ…なるほど 🙁 (edited)
Avatar
これができるとMonadやApplicativeをProtocolとして宣言できるようになりますが、現在はないので (edited)
12:45 AM
Sequenceのmap/flatMapはArray<T>へ変換されてますね
Avatar
そうですよねー…
Avatar
ついに高カインド型が欲しいところまで来たんですか
Avatar
こういうことがしたいケースでは,Sequence.map みたいに具体型を特定してしまうか,適合型ごとに実装するしかないんですねぇ.
Avatar
イナミさんがiOSDCで話してたラムダキューブの右方向の機能ですな
Avatar
多項式を protocol 化しようとして(一変数・多変数など色々な種類があって個別に同じコードを書くのが嫌なので),係数環を変えるような map を実装したいのだけどできない,という感じです. public func mapCoefficients<R2: Ring>(_ f: (R) -> R2) -> Polynomial<x, R2> { .init(elements: elements.mapValues{ f($0) }) }
Avatar
右じゃなくて奥か
Avatar
例えば整数係数の多項式を有理数係数と思いたい,というようなケース.
12:50 AM
これを多項式の種類ごとに実装するのではなく,protocol として宣言して extension でまとめて書きたい,という思いからの疑問でした.
12:54 AM
代わりに struct を一個にして色々な generic 型を持たせることで種類を分けて,激しめに extend する方向も考えたのですが,異なる条件で同じ protocol に conditionally conform するということができないので,それも諦めました🙄
Avatar
まさにこれですね
Avatar
他にも写像型を protocol 化しようとして,合成演算 ∘ が protocol レベルで宣言できずに困ったこともありました. public struct Map<X: SetType, Y: SetType>: MapType { public typealias Domain = X public typealias Codomain = Y private let f: (X) -> Y public init(_ f: @escaping (X) -> Y) { self.f = f } public static func ∘<W>(g: Map<X, Y>, f: Map<W, X>) -> Map<W, Y> { g.composed(with: f) } } (edited)
Avatar
そうですね、、共通の一つのコンテナに固定されちゃいます
Avatar
Sequence.map が全部 [T] になっちゃうことにストレスを感じてる人も多そうなので,将来的には対応が期待できそうな感じですかね 😗
Avatar
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
12:59 AM
マニフェストでは 「Maybe」に入ってますね
Avatar
その上の Generic value parameters と合わせて是非やっていただきたいですねw
1:02 AM
こないだ質問した Private conformances についても Unlikely に入ってたんですね
1:02 AM
当面は struct ごとに実装してく方向で対処します,ありがとうございました!
1:09 AM
上のを manifest にある記法で書くと: func mapCoefficients<P ~= Self>(_ f: (R) -> P.R) -> P という感じですかね.是非こう書きたい!
Avatar
omochimetaru 10/3/2019 1:50 AM
fの型の方からP.Rがそうやって決まるのか。制約はPがSelfと同じ型コンストラクタであると。面白い書き方ですね。
Avatar
是非こう書きたい(2回目)
3:07 AM
ところでいつの間にか struct の property や func でも Self って使えるようになってたんですね.長い名前のとき毎回書かなきゃいけないのが冗長だったり,protocol に移すとき Self に直さなきゃいけなかったりで面倒だったので地味に嬉しい 😬 (edited)
Avatar
omochimetaru 10/3/2019 3:07 AM
Swift5.1で実装されました
Avatar
いえーい✌️
Avatar
omochimetaru 10/3/2019 3:07 AM
なんか随分前にacceptしてたんだけど、誰も実装してなかったのを、
3:07 AM
有志が実装してPRを投げてた気がする
Avatar
おー,有志に感謝🙏
Avatar
protocol A, B に同シグネチャの関数があって,それぞれ protocol extension でデフォルト実装を入れているとして,struct X: A, B とすると ambiguity からオーバーライドさせられますが,「A の方の実装を採用する」というようなことはできないんでしょうか? struct X: A, B { func common() { (self as A).common() } } こんな感じで…
1:40 PM
あ,A, B は Self つきの protocol で as が使えない奴です.
1:41 PM
上のコードをそのまま書くと Protocol 'A' can only be used as a generic constraint because it has Self or associated type requirements となるタイプのものです.
Avatar
protocol extensionのデフォルト実装は呼べないので
1:43 PM
static関数を外においてextensionと実装強制の双方からコールするのが良いです
Avatar
なるほどなるほど.
1:43 PM
extension で internal func _commonA() のようなものをつくっておいて,そちらを呼ぶというのもありですかね?
Avatar
static func common<T: P>(_ self: P) こんな感じのを作っておけばオッケー
1:44 PM
あ、それもいけるかも。
Avatar
OK です!
Avatar
protocol A { func common() } extension A { func commonAImpl() { ... } func common() { commonAImpl() } } protocol B { 略 } こんな感じですね
1:45 PM
うまくいきそう。
Avatar
できました👍👍
👏 1
Avatar
omochimetaru 10/4/2019 1:34 AM
ジェネリックシグネチャを通すことで属性を絞り込んで明示的にディスパッチするテクはたまに使えますね
Avatar
Swift 5.1でフレームワークを作っています。URL: https://github.com/rizumita/Seda このプロジェクトの中にSedaSampleAppというiOSサンプルアプリがあるのですが、そのライブラリをインポートしてこのアプリをシミュレーター用にビルドすると Undefined symbols for architecture x8664 になってしまいます。 ``` Undefined symbol: (extension in Seda):Seda.StatefulView< where A.Action: Seda.ActionType>.dispatch(A.Action) -> () Undefined symbol: (extension in Seda):Seda.StatefulView.state.getter : A.Substate Undefined symbol: (extension in Seda):Seda.StatefulView< where A.State == A.Substate>.stateKeyPath.getter : Swift.KeyPath<A.State, A.State> Undefined symbol: (extension in Seda):Seda.StatefulView.binding<A>(: Swift.KeyPath<A.Substate, A1>, set: (A1) -> Seda.ActionType) -> SwiftUI.Binding<A1> ``` インポートではなくライブラリのファイルをサンプルアプリターゲットに直接追加してビルドするとビルド・実行できます。 ライブラリのビルド時にシンボルが正しく作成されてないみたいなのですが、何を修正すればいいかさっぱり分かりません。どう修正すればいいかお分かりでしたら教えていただけないでしょうか?
Seda is Redux+Elm Cmd framework for SwiftUI. Contribute to rizumita/Seda development by creating an account on GitHub.
Avatar
Kishikawa Katsumi 10/5/2019 3:39 AM
Seda.frameworkのBase SDKがmacOSだからじゃないかな。
3:40 AM
なんかSeda.frameworkターゲットのビルド設定がおかしいように見えます。
Avatar
Kishikawa Katsumi 10/5/2019 3:49 AM
でももう一つのサンプルアプリはリンクできてるのか。なんでしょうね。これ。
Avatar
Kishikawa Katsumi 10/5/2019 3:59 AM
ビルド済みのSeda frameworkを別のプロジェクトにImportすると問題ないので、プロジェクト構成の問題っぽいですね。
Avatar
omochimetaru 10/5/2019 4:03 AM
僕も見てみました。 ビルドできない問題は同じエラーで再現しました。 とりあえず、SedaSampleAppのソースを空にするとビルドできました。 岸川さんの「別のプロジェクトでいけた」は、使ってる側のコードが無いからで、同じ状況かも?
4:05 AM
CounterView, CountHistoryView, OptViewのいずれかをプロジェクトに追加した時点で
4:05 AM
エラーが出るようになる。
Avatar
問題のプロパティ・メソッドを使用するとエラーが発生するようになります。
Avatar
Kishikawa Katsumi 10/5/2019 4:13 AM
ほんとですね。ある程度コードをコピー&ペーストしてたけどそれじゃ再現しなくて
4:13 AM
全部ファイルをコピーしたら再現しました。
Avatar
omochimetaru 10/5/2019 4:14 AM
今の所特定のコードの書き方がコンパイラのバグを踏むんじゃないかと予想してます (edited)
Avatar
Kishikawa Katsumi 10/5/2019 4:14 AM
ということはツールチェーンの問題かなあ。
Avatar
omochimetaru 10/5/2019 4:14 AM
SwiftUI関連のバグかどうかも疑ってる。
Avatar
バグの可能性ですか。
Avatar
omochimetaru 10/5/2019 4:16 AM
はい。少なくともコンパイルフェーズは通ってるので
4:16 AM
リンクだけ通らないってのはSwiftの世界観だと普通起きないので。
4:16 AM
ビルド構成に間違いがあればそういうこともあるけどいまのところ変な部分は見当たらない。
Avatar
omochimetaru 10/5/2019 4:25 AM
むむむ
4:26 AM
public protocol StatefulView where Self: View { ^^^^^^^^^^^^^^^^ここ 消すとビルドできますね。 (edited)
4:29 AM
public protocol StatefulView : View {
4:29 AM
↑これでもビルドできます。
Avatar
おお
Avatar
omochimetaru 10/5/2019 4:31 AM
protocol P where Self : <クラス名> は やることがあるけど、 protocol P where Self : <プロトコル名>は普通やらないような? protocol P : <プロトコル名>と意味の違いがあるんだろうか。
4:31 AM
protocol P where Self : <クラス名> は やることがあるけど、
いや、これもSwift5から、 protocol P : <クラス名> と書けるようになったんだった。
4:32 AM
where Self : <プロトコル名> って書いたときの取り扱いにコンパイラにバグがある気がします。
Avatar
なるほど。ありがとうございました!
Avatar
vicktorManuel 10/8/2019 9:07 AM
Hello guys , I have some questions,, please help me! Now I studying for my test in December , I study a lot topics kind Swift , I have this question: what is better study and why. Rxswift or combine, why is better know reactive programming ? . What topics are important for my test (edited)
9:08 AM
Thank you so much and sorry for my beginners question.
Avatar
omochimetaru 10/8/2019 9:13 AM
I think most major value of stream style is that we can solve callback hell problem by them. https://techblog.yahoo.co.jp/javascript/nodejs/callback-to-promise/
こんにちは。言語サポート(Node.js)チームの伊藤(@koh110)です。Node.js v10 も10月にLTSとなり async/await によるフロー制御は当たり前のように利用されるようになってきました。JavaScript...
9:16 AM
↑This article is written about Promise, async await in JavaScript. They are not stream but can avoid callback hell. Same worth is in streams.
9:20 AM
Streams are more high level abstraction than Promises. They can encapsulate about start of asynchronous operations. A one of good example is .retry operator in ReactiveX.
👌 1
9:22 AM
If you use stream more agressive, you can get power of immutable programming and safety. Everythins is a stream meme says about this style. https://www.google.com/search?q=everything+is+stream&client=safari&rls=en&sxsrf=ACYBGNSrL5EOg_7a__un_phY7QRiR-SjEw:1570526439303&source=lnms&tbm=isch&sa=X&ved=0ahUKEwjippn0qozlAhXvGKYKHWI2DNYQ_AUIESgB&biw=1430&bih=779 (edited)
👌 1
Avatar
vicktorManuel 10/8/2019 10:59 AM
Thank you so much for your response omochi San
Avatar
@vicktorManuel Basically I think Combine (as well as SwiftUI) can wait, at present RxSwift is still comparatively better to learn. Here's why: 1. Combine is too new and may have lots of destructive changes in the future, just like when Swift came out; where RxSwift is based on a well developed theory ReactiveX, which has been used on products for many years and has a very wide user base. 2. Combine can only be used on iOS later than 13, where RxSwift doesn't have that kind of limitation 3. Actually combine doesn't declare itself as a "Reactive Framework", therefore you don't see concepts like Stream, or Hot/Cold observables etc. Instead, Combine is just a framework provides a declarative Swift API for processing values over time (according to Combine's document). It has many things similar with Reactive programming, but it's not a Reactive tool. But personally, I would prefer Combine much better over RxSwift.
👌 1
Avatar
vicktorManuel 10/9/2019 6:21 AM
Thank you so much for your answers! Very complete answer, ありがとうございます
🎉 1
Avatar
#swiftbot-sandbox のコンパイルできないやつ、どこから String が出てきたのかと思ったけど、これにマッチさせようとしているのかな。 https://github.com/apple/swift/blob/da61cc8cdf7aa2bfb3ab03200c52c4d371dc6751/stdlib/public/core/MigrationSupport.swift#L547-L555
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
The review of SE-0267 — where clauses on contextually generic declarations begins now and runs through October 31, 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 yo...
1:09 AM
外側のパラメータに関するwhereを定義本体に書けるように文法の制限を廃止する提案
1:11 AM
型制約上の意味が同じでもマングリングが異なる記法が生まれる事になるので、その2種の間でのABI非互換が産まれるという指摘がされてるけど、 その問題は今もすでにあるという指摘もあった。
Avatar
あれ?これ元から出来ませんでしたっけ?
Avatar
struct S<T> { func f() where T == Int { } // ^ 'where' clause cannot be attached to a non-generic declaration }
3:24 AM
↑の例だとSのパラメータTについてはfuncのところでは書けない。func fのパラメータ<X>だったら書ける。 (edited)
Avatar
なるほど
3:36 AM
んーーー?なんか裏技あった気がするな
Avatar
裏技ってこれ? extension Array { func compact<T>() -> [T] where T? == Element { [] } }
Avatar
落ち着いたら記憶を掘り起こすんでお待ちを (edited)
🙂 1
Avatar
class Manul {} class Mike {} protocol NekoCargoBase { associatedtype InCargoCat } class NekoCargo<NekoType> {} extension NekoCargo: NekoCargoBase { typealias InCargoCat = NekoType } extension NekoCargo where InCargoCat == Manul { func meou() -> String { return "マヌルネコだよ!にゃーん" } } extension NekoCargo where InCargoCat == Mike { func meou() -> String { return "ミケネコだよ!にゃーん" } } let cargo: NekoCargo<Manul> = .init() print(cargo.meou()) なんかさっと思いついたものですが自信がない・・・ (edited)
1:26 AM
あ、でもfuncのところでかけないのは同じか
Avatar
型パラがconformanceを持ってる時に、それ自体は指定できないがprotocolが持つassoctypeなら出来た気がするんですよね
1:29 AM
ん、ダメだな
1:33 AM
なにか親しい議論あった気がするんですよね~と検索してみたがヒットしたのは https://discordapp.com/channels/291054398077927425/291054454793306112/372686348395610114 だった。
1:38 AM
うーんextensionで書ききれない制約を、initのタイミングで縛ってごまかすっていうコードを書いた記憶があるんだが
1:38 AM
どこにしまったかな。。
Avatar
extensionで書ききれない制約を、initのタイミングで縛ってごまかす
そもそも今回のやつは、型としての制約の表現能力が上がる話ではないので
3:01 AM
元からextensionで書けないものはこの変更が入っても書けないはず。
3:02 AM
単に今までextensionで書けたものが本体でも書けるように記法が増えるというもの。
3:02 AM
(ただ記法が増えてるだけじゃなくてABIは増える)
Avatar
omochimetaru 11/2/2019 6:59 PM
The review of SE-0269: Increase availability of implicit self in @escaping closures when reference cycles are unlikely to occur begins now and runs through November 12, 2019. The proposal is written by @Jumhyn. Reviews are an important part of the Swift evolution process...
7:00 PM
execute { [self] in let foo = doFirstThing() performWork(with: bar) doSecondThing(with: foo) cleanup() }
7:00 PM
明示的なselfキャプチャーによってクロージャ内でメソッドみたいにself.が不要
7:02 PM
軽く話してるけどこれ系すすまないよな〜と思ったらレビュー開始してた
Avatar
これ escaping nonescaping なら self 省略できることと一貫性があっていいね。 (edited)
Avatar
non escapingですか?
Avatar
ああ、nonescaping
Avatar
一貫性というのはクロージャの中でself省略するという記法が新しいものではないのが好ましいって意味です?
Avatar
SE-0269: Increase availability of implicit self in @escaping closures when reference cycles are unlikely to occur
12:45 AM
タイトルがこれだから、サイクルが起きない時という意味で同じなのか
Avatar
@escaping のときに明示的な self が必要なのはキャプチャが起こっていることを意識させるためだと理解してるけど、 [self] があればその役割はすでに果たされているので、 @nonescaping のときに self が省略できることを考えると、 @escaping かつ [self] がある場合もクロージャ内で self が省略できて良いはずという意味での一貫性。
Avatar
omochimetaru 11/6/2019 7:59 AM
@escaping のときに明示的な self が必要なのはキャプチャが起こっていることを意識させるため
あ〜なるほど。この認識は無かったけど、たしかに。
Avatar
@swift-5.1.5 struct AError: Error {} struct BError: Error {} func foo<E: Error>(_ errors: [E]) { print(errors.map { "\($0)" }.joined(separator: ", ")) } let errors: [Error] = [AError(), BError()] foo(errors)
Avatar
AError(), BError()
Avatar
@swift-5.1.5 struct AError: Error {} struct BError: Error {} func foo<E: Error>(_ errors: [E]) { print(errors.map { "\($0)" }.joined(separator: ", ")) } foo([AError(), BError()])
Avatar
exit status: 1 with stderr:<stdin>:8:5: error: in argument type '[Any]', 'Any' does not conform to expected type 'Error' foo([AError(), BError()]) ^
Avatar
Error 型が Error プロトコルに適合するようになったけど、 [AError(), BError()] みたいなのの型を [Error] と推論する部分の実装が足りてない?
1:41 PM
ちがった
1:41 PM
as [Any] をつけろと言われてるのか。
1:41 PM
ん?上のエラーは違うか
1:41 PM
@swift-5.1.5 struct AError: Error {} struct BError: Error {} let errors = [AError(), BError()]
Avatar
exit status: 1 with stderr:<stdin>:4:14: error: heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional let errors = [AError(), BError()] ^~~~~~~~~~~~~~~~~~~~ as [Any]
Avatar
@swift-5.1.5 struct AError: Error {} struct BError: Error {} let errors = [AError(), BError()] as [Error]
Avatar
no output
Avatar
さっきの↓では [Any] に推論された上でエラーになってる? <stdin>:8:5: error: in argument type '[Any]', 'Any' does not conform to expected type 'Error' foo([AError(), BError()])
Avatar
omochimetaru 11/6/2019 1:43 PM
複数の候補がある場合は一つ通れば良いので
1:43 PM
探索されてないですね
Avatar
Error を特別に Error に適合させたときに漏れたかな?
Avatar
omochimetaru 11/6/2019 1:44 PM
普通のPだとどうなるか気になりますね
Avatar
普通の PP に適合しないから
Avatar
omochimetaru 11/6/2019 1:45 PM
@objcをつけると
1:45 PM
する
Avatar
@swift-5.1.5 protocol P {} struct A: P {} struct B: P {} let values = [A(), B()]
Avatar
exit status: 1 with stderr:<stdin>:5:14: error: heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional let values = [A(), B()] ^~~~~~~~~~ as [Any]
Avatar
↑この挙動は共通みたい。 === ↓ @objc つけた場合も同じ (edited)
1:49 PM
1> import Foundation 2. 3. @objc protocol P {} 4. class A: P {} 5. class B: P {} 6. 7. func foo<X: P>(_ values: [X]) { 8. print(values.map { "\($0)" }.joined(separator: ", ")) 9. } 10. 11. foo([A(), B()]) error: repl.swift:11:5: error: in argument type '[Any]', 'Any' does not conform to expected type 'P' foo([A(), B()]) ^
1:49 PM
1> import Foundation 2. 3. @objc protocol P {} 4. class A: P {} 5. class B: P {} 6. 7. func foo<X: P>(_ values: [X]) { 8. print(values.map { "\($0)" }.joined(separator: ", ")) 9. } 10. 11. foo([A(), B()] as [P]) __lldb_expr_1.A, __lldb_expr_1.B
1:53 PM
ぱっと見、それっぽいバグレポないなぁ。
Avatar
omochimetaru 11/6/2019 1:55 PM
そもそも <X: P> に対して (any) X==Pを発見するケースってあるんかな (edited)
1:56 PM
既に構成されてる P から推論するケースじゃなくて
1:56 PM
直接のPは書かれてないケース
1:57 PM
直感的には推論がちょっと重くなりそうな気がする、ErrorのSelf-conformのスレでも気にしていた人がいたな
Avatar
omochimetaru 11/6/2019 2:04 PM
@swift-5.1.5 struct AE: Error {} struct BE: Error {} func f<X: Error>(_ a: X, _ b: X) {} f(AE(), BE())
Avatar
exit status: 1 with stderr:<stdin>:4:9: error: cannot convert value of type 'BE' to expected argument type 'AE' f(AE(), BE()) ^~~~
Avatar
omochimetaru 11/6/2019 2:05 PM
@swift-5.1.5 struct AE: Error {} struct BE: Error {} func f<X: Error>(_ a: X, _ b: X) {} f(AE(), BE() as Error)
Avatar
no output
Avatar
omochimetaru 11/6/2019 2:06 PM
うーむ
2:07 PM
CombineやReactiveSwiftで不便なシーンがあったりするだろうか
2:08 PM
見つからない暗黙変換があるということで普通にバグ扱いなのかなあ
2:09 PM
bugs見たけど error の検索性が悪すぎて全くわからんw
2:10 PM
微妙なラインだし報告するのが良いやつな気がしてきてる
Avatar
error の検索性が悪すぎて全くわからんw
それw protocol とか色々入れて検索してみたけど、ぱっと見ではなさそう。
2:13 PM
@swift-5.1.5 struct AError: Error {} struct BError: Error {} func foo<E: Error>(_ error: E) {} foo(AError())
Avatar
no output
Avatar
↑これはいけるっぽい。 (edited)
Avatar
omochimetaru 11/6/2019 2:13 PM
それは E == AError だと思う
Avatar
あ、そうだった
2:13 PM
ボケてた
2:13 PM
最小ケースを作ろうとして削りすぎたw
Avatar
これって型パラメータ一般の問題かと思ってたけど、 heterogeneous collection のリテラル限定の問題なのかな・・・。
Avatar
omochimetaru 11/7/2019 8:09 AM
いや、2引数のケースを試したので、リテラルより一般的です
Avatar
ああ、壊れ方が違うだけか。
8:09 AM
複数引数のときは、一つ目の引数の型として推論されて
8:09 AM
二つ目の引数の型が違うと言われた。
Avatar
omochimetaru 11/7/2019 8:10 AM
solutionの候補は複数あるけど
8:10 AM
全ての失敗した候補の失敗した理由は表示されないので
Avatar
@swift-5.1.5 struct AError: Error {} struct BError: Error {} struct List<Element> { init(_: Element...) {} } func foo<E: Error>(_ errors: List<E>) {} foo(List(AError(), BError()))
Avatar
exit status: 1 with stderr:<stdin>:10:20: error: cannot convert value of type 'BError' to expected argument type 'AError' foo(List(AError(), BError())) ^~~~~~~~
Avatar
omochimetaru 11/7/2019 8:10 AM
失敗した候補の中から最も正解に近そうなエラーを出すように選んでる
Avatar
@swift-5.1.5 struct AError: Error {} struct BError: Error {} struct List<Element> { init(_: Element, _: Element) {} } func foo<E: Error>(_ errors: List<E>) {} foo(List(AError(), BError())) (edited)
Avatar
exit status: 1 with stderr:<stdin>:10:20: error: cannot convert value of type 'BError' to expected argument type 'AError' foo(List(AError(), BError())) ^~~~~~~~ (edited)
Avatar
@swift-5.1.5 struct AError: Error {} struct BError: Error {} func foo<E: Error>(_ errors: (E, E)) {} foo((AError(), BError()))
Avatar
exit status: 1 with stderr:<stdin>:6:1: error: cannot invoke 'foo' with an argument list of type '((AError, BError))' foo((AError(), BError())) ^ <stdin>:6:1: note: expected an argument list of type '((E, E))' foo((AError(), BError())) ^
Avatar
@swift-5.1.5 class Base {} class A: Base {} class B: Base {} func foo<X: Base>(_ values: [X]) {} foo([A(), B()])
Avatar
no output
Avatar
omochimetaru 11/7/2019 8:17 AM
supertypeは見つかるんですよね
Avatar
@swift-5.1.5 class Base {} class A: Base {} class B: Base {} func foo<X: Base>(_ values: (X, X)) {} foo((A(), B()))
Avatar
no output
Avatar
omochimetaru 11/7/2019 8:17 AM
(継承に関する)supertype境界の合成は常に行われる (edited)
8:17 AM
existentialは別枠
Avatar
@swift-5.1.5 class Base {} class A: Base {} class B: Base {} struct List<Element> { init(_: Element...) {} } func foo<X: Base>(_ values: List<X>) {} foo(List(A(), B()))
Avatar
no output
Avatar
@swift-5.1.5 class Base {} class A: Base {} class B: Base {} struct List<Element> { init(_: Element, _: Element) {} } func foo<X: Base>(_ values: List<X>) {} foo(List(A(), B()))
Avatar
no output
Avatar
全パターン OK だな。
8:21 AM
一方で、↓はできるから、型パラメータの self-conformance の考慮漏れってことでいいのかな。 @swift-5.1.5 struct AError: Error {} struct BError: Error {} let errors: [Error] = [AError(), BError()]
Avatar
no output
Avatar
omochimetaru 11/7/2019 8:22 AM
ambiguousになる場合を除いて、同じ式を型アノテートして型チェックが通せる場合に
8:22 AM
型アノテートが無い場合でも必ず型チェックが通る
8:22 AM
っていうのが型推論器の規約なら、バグって話になると思います
8:23 AM
計算量を考慮して特殊なケースでサボる仕様なら仕様で
8:23 AM
いずれにせよ報告してみないと確定しないやつだと思います
8:27 AM
立てた。
8:33 AM
バグじゃなくても as [Error] を明記してねっていうエラーメッセージの方が良さそう。
Avatar
@swift-5.1.5 func foo<A: Any>(_ value: A) {} let a: Any = 42 foo(a)
Avatar
no output
Avatar
Any は self-conformance と言っていいのかな?
8:59 AM
Any はプロトコルじゃないんだっけ?
9:03 AM
@swift-5.1.5 func foo<A: AnyObject>(_ value: A) {} let a: AnyObject = \String.count foo(a)
Avatar
no output
Avatar
↓これ知らなかった。 @swift-5.1.5 protocol P {} struct FooError: Error, P {} func foo<E: Error>(_ error: E) {} let e1: Error = FooError() foo(e1) // OK let e2: Error & P = FooError() foo(e2) // NG
Avatar
exit status: 1 with stderr:<stdin>:10:1: error: protocol type 'Error & P' cannot conform to 'Error' because only concrete types can conform to protocols foo(e2) // NG ^
Avatar
↓これは OK @swift-5.1.5 protocol P {} struct FooError: Error, P {} func foo<E: Error>(_ error: E) {} let e1: Error = FooError() foo(e1) // OK let e2: Error & P = FooError() //foo(e2) // NG let e3: Error = e2 foo(e3) //OK
Avatar
no output
Avatar
This self-conformance does not extend to protocol compositions including the Error protocol, only the exact type Error. It will be possible to add such compositions in the future, but that is out of scope for Swift 5.
https://github.com/apple/swift-evolution/blob/master/proposals/0235-add-result.md#adding-swifterror-self-conformance
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 11/8/2019 1:33 AM
Anyは空のprotocol compositionだから
1:33 AM
制約の無いexsitentialであってそれ自体はprotocolではないという認識
1:35 AM
あ、どうなんだろう、protocolと考えても矛盾は無い・・・?
1:35 AM
Errorが合成に変なしばりあるの面白いですね
Avatar
結構際どいけど、Anyは空のcompositionであるから、existentialもcoformできるのであって、self conformingではなさそう
Avatar
omochimetaru 11/8/2019 1:38 AM
@swift-5.1.5 func f<X: Any>(_ x: X) {}
Avatar
no output
Avatar
omochimetaru 11/8/2019 1:38 AM
これ書けるのかよ。
1:39 AM
お、書けるけど、
1:39 AM
f<X>でもf<X: Any>でも同じシンボルになる $s6code011fyyxlF
1:39 AM
つまり書いても書いて無くても同じ
1:40 AM
@swift-5.1.5 protocol P: Any {}
Avatar
no output
Avatar
omochimetaru 11/8/2019 1:40 AM
基本的にprotocolとして扱えるっぽいなw
1:40 AM
意味が常に無だけど
Avatar
Any はともかく AnyObject は self-conformance ? @swift-5.1.5 func foo<A: AnyObject>(_ value: A) {} let a: AnyObject = \String.count foo(a)
Avatar
no output
Avatar
ですね
Avatar
any P が導入されたら Any の表記に違和感が出てきそうな気がしてるんですがどうでしょう?
6:53 AM
any P & Q とかを考えると anyany () とかかな?でも Never との整合性が・・・。
Avatar
omochimetaru 11/8/2019 6:54 AM
someもあるし良いのでは
Avatar
some だけで型を表せる??
7:21 AM
@swift-5.1.5 func foo() -> some { 42 }
Avatar
exit status: 1 with stderr:<stdin>:1:20: error: expected type for function result func foo() -> some { 42 } ^ <stdin>:1:22: warning: integer literal is unused func foo() -> some { 42 } ^~
Avatar
omochimetaru 11/8/2019 7:21 AM
大文字小文字のことを言っているのかと思った。
Avatar
@swift-5.1.5 func foo() -> some Any { 42 }
Avatar
no output
Avatar
some Any
Avatar
omochimetaru 11/8/2019 7:22 AM
some Any からすると any Any?
Avatar
any Any はいいかもだけど、 any Any が top で Never が bottom ってなんか微妙やんね。
Avatar
omochimetaru 11/8/2019 9:06 AM
Dear Swift folks, Here is a pitch to plug a small hole in the stdlib API by providing a reliable method to retrieve the address for any directly addressable stored property inside a class instance. The need to work with such addresses comes up particularly often when we try ...
9:07 AM
クラスインスタンスのプロパティのストレージアドレスを取れるようにするピッチ
9:11 AM
マジで用途が限定的だけど言語としてはあってよさそう
Avatar
https://github.com/apple/swift-evolution/blob/master/proposals/0223-array-uninitialized-initializer.md Arrayのuninitialized initializerが導入されて久しいですが、 UnsafeMutableBufferPointerのn番目の要素をinitializeのするのに var p = bp.baseAddress! + n p.initialize(to: value) みたいにちょっと長くなるのが気になってるんですが bp.initialize(index: n, to: value)みたいなのを導入するピッチ投げたら良いんですかね? インターフェース的にこうしたほうが良さそうとかあります?
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 11/9/2019 2:43 AM
baseAddress.advanced.initializeは?
Avatar
あーそれできますね。
2:45 AM
一応bp.initializeなら範囲チェック入れられるというメリットはありますがunsafeな時点で微妙か……
Avatar
norio_nomura 11/9/2019 4:23 AM
bp[n] = value
Avatar
initializeしたい場合なんですよね。 (uninitialize状態で書き込んだときどういう弊害が起こるのかはイマイチ理解できてないんですが)
Avatar
norio_nomura 11/9/2019 7:11 AM
プロポーザルのサンプルにも書かれてる方法だけど。
Avatar
んー確かにありますね。stablyPartitionedのほうだけ見てました。
Avatar
omochimetaru 11/9/2019 7:29 AM
bp[n] = value は左辺がinitializedな状態で使わないと不正ではないか
7:29 AM
今はメモリがuninitializedな状態なので
7:29 AM
誤った仮定をおくと、無意味なビット列に対して破棄操作が起こってしまう。
7:29 AM
Intみたいなtrivialな型の場合は問題は起きない。
Avatar
中身によるってことですか?
Avatar
omochimetaru 11/9/2019 7:31 AM
中身って?
Avatar
UnsafeMutableBufferPointer<T>のT (edited)
Avatar
omochimetaru 11/9/2019 7:32 AM
うん、initialized/uninitializedを無視しても良いかどうかは型による (edited)
Avatar
@swiftbot class MyClass { var i: Int init(_ i: Int) { print("init: \(i)") self.i = i } deinit { print("deinit: \(i)") } } do { print("# init array") var array = [MyClass(1), MyClass(2)] print("# assign 3") array[0] = MyClass(3) print("# assign 4") array.withUnsafeMutableBufferPointer { bp in bp.baseAddress!.initialize(to: MyClass(4)) } print("# exit do") }
🛠 1
Avatar
swiftbot BOT 11/9/2019 7:54 AM
Author icon
t.ae
class MyClass { var i: Int init(_ i: Int) { print("init: \(i)") self.i = i } deinit { print("deinit: \(i)") } } do { print("# init array") var array = [MyClass(1), MyClass(2)] print("# assign 3") array[0] = MyClass(3) print("# assign 4") array.withUnsafeMutableBufferPointer { bp in bp.baseAddress!.initialize(to: MyClass(4)) } print("# exit do") }
Version:
swift-5.1-RELEASE
Output:
# init array init: 1 init: 2 # assign 3 init: 3 deinit: 1 # assign 4 init: 4 # exit do deinit: 4 deinit: 2
Error:
Avatar
完全に理解した
Avatar
omochimetaru 11/9/2019 7:56 AM
そうだね、この場合は破棄がされない方の間違いだから3がリークしてる (edited)
Avatar
逆に未初期化状態のところに代入しようとするとdeinitでおかしなことになるわけですね。
Avatar
omochimetaru 11/9/2019 7:59 AM
0ビットで埋まってればnilポインターだから何も起きないけど、0クリアされていない場所だったら、アドレスとみなしてむりやりdeinitしようとしてクラッシュするね (edited)
8:01 AM
uninitialized initializerのモチベーション自体が、そのゼロクリアをスキップすることでパフォーマンスを最適化するAPIだから
8:01 AM
当然ゼロクリアされていないメモリ領域があてがわれた場合の事を適切に考えないといけない
Avatar
norio_nomura 11/9/2019 8:10 AM
なるほど。
Avatar
The review of SE-0270: Add Collection Operations on Noncontiguous Elements begins now and runs through November 21, 2019. The proposal is written by @nnnnnnnn. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum t...
1:32 AM
Rangeを複数くっつけてコレクションとして振る舞うRangeSetの審査
1:32 AM
唐突に凝ったのが来た Pitch見逃してたんかな
Avatar
var numbers = Array(1...15) // Find the indices of all the even numbers let indicesOfEvens = numbers.indices(where: { $0.isMultiple(of: 2) }) // Perform an operation with just the even numbers let sumOfEvens = numbers[indicesOfEvens].reduce(0, +) // sumOfEvens == 56 // You can gather the even numbers at the beginning let rangeOfEvens = numbers.gather(indicesOfEvens, justBefore: numbers.startIndex) // numbers == [2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15] // numbers[rangeOfEvens] == [2, 4, 6, 8, 10, 12, 14] // Reset `numbers` numbers = Array(1...15) // You can also build range sets by hand using array literals... let notTheMiddle: RangeSet = [0..<5, 10..<15] print(Array(numbers[notTheMiddle])) // Prints [1, 2, 3, 4, 5, 11, 12, 13, 14, 15] // ...or by using set operations let smallEvens = indicesOfEvens.intersection( numbers.indices(where: { $0 < 10 })) print(Array(numbers[smallEvens])) // Prints [2, 4, 6, 8]
1:44 AM
↑歯抜けのindexの並びみたいなもんを扱える
Avatar
Hi folks! Here's a pitch to fill a missing chunk of functionality in the standard library around noncontiguous ranges of elements. Please take a look at the draft proposal below, and/or try out this new functionality by using the SwiftPM package here: https://github.com/nate...
Avatar
お。
Avatar
The review of SE-0269: Increase availability of implicit self in @escaping closures when reference cycles are unlikely to occur begins now and runs through November 12, 2019. The proposal is written by @Jumhyn. Reviews are an important part of the Swift evolution process...
7:12 AM
これって、
7:13 AM
let a = obj() let f = { [self = a] in hoge() // call a.hoge } これできんのかな。
7:13 AM
できるなら他の言語のスコープ文みたいな機能が爆誕してる事になる
Avatar
テストケース見る限り、それはできなさそう。 https://github.com/apple/swift/pull/23934/files#diff-d7c6f9df7278996950aba8a8ba87de75R176
doStuff({ [self = self.x] in x+1 }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-warning {{capture 'self' was never used}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}}
Avatar
お、なるほど。ありがとうございます。まーそうか。
Avatar
doStuff({ [self = self.x] in x+1 })
1:12 AM
英語がわからないのですが、これでキャプチャされるのは self ではなく self.x だけですか?
Avatar
そうです、キャプチャリストは [var = exp] の形でかけて、クロージャを作る時にexpが評価されます
Avatar
ありがとうございます。なるほどです。
12:16 AM
そうなるとオーナーシップ関連のバグが仕込めそうですね。気を付けないと。
Avatar
へんな状況を色々考えたけど僕にはオーナーシップ関連のバグが作れなかったw
6:39 AM
大丈夫なのかな?
Avatar
キャプチャリストの仕様とは関係ない話なら、classをプロパティに持つstructをキャプチャに絡ませるとリークが避けられない、みたいな話ならありますよ
Avatar
こうやればいいのかな? struct A { var x: Int = 0 { didSet { doSomething() } } } func hoge() { var a = A() // take ownership of a. DispatchQueue.global().async { [x = a.x] in // take ownership of a ??? sleep(100) x = 9 } // release ownership of a. } の時にdoSomething()が呼び出されるのかどうか というか、aのオーナーシップがどうなるのか。 (edited)
Avatar
それだと xの型は let x: Intで、 x = 9はエラーになりそう それと、x = a.xの評価はクロージャの構築時になるので、aのオーナーシップはクロージャは取りません クロージャ構築時にa.xを読み取るだけでaは無くなる
Avatar
キャプチャリストはオーナーシップの指示だけのものと思ってました。
8:27 AM
キャプチャリストに入れるとクロージャ内ではimmutableになるんですね。
8:28 AM
根本的なところが間違ってた
Avatar
func highFunc(_ f: () -> Void) { f() } func main() { var a: Int = 3 highFunc { [a] in a = 5 // Cannot assign to value: 'a' is an immutable capture } } (edited)
8:29 AM
たしかに、varのmutable captureを
8:29 AM
capture listで書く方法がなさそうですね
Avatar
それが出来ると壊れるので、出来ないのが正解の気がします
Avatar
func main() { var a: Int = 3 highFunc { () in a = 5 } } ↑これはできるよ。
Avatar
それはescapingじゃないならokの気がする (edited)
Avatar
escapingじゃないからOKの理屈なら元記法も通らないと一貫性が無くない?
8:35 AM
暗黙のキャプチャーは何らかの明示的なcapture list表記に対応すると思ってたんだけど
Avatar
キャプチャリストでmutability伝搬できちゃうとescapingで壊れない?
Avatar
暗黙のキャプチャーのときだけできるパターンがあるのは変
Avatar
というかnon-escapingだとそもそもcapture不要の認識であった
Avatar
class C { var f1: (() -> Void)? var f2: (() -> Void)? } func proc(c: C) { var a: Int = 3 c.f1 = { a += 1 } c.f2 = { print(a) } } func main() { let c = C() proc(c: c) c.f1?() c.f2?() } main() // => 4
8:39 AM
↑escapingで暗黙のcapture(var a)する例
Avatar
クロージャのキャプチャは、クロージャ作成時点での変数の値をローカル変数(的な物)にコピーするだけなので、 let closure: () -> Void = { [x] in print(x) }let closure: () -> Void do { let x = x closure = { in print(x) } } とほぼ同意です。
Avatar
お、その書き換えは面白いですね。明示的なキャプチャーを暗黙のキャプチャーに書き換えている。
Avatar
public func foo1() -> () -> Void { var x = 1 let closure: () -> Void = { [x] in print(x) } return closure } public func foo2() -> () -> Void { var x = 1 let closure: () -> Void do { let x = x closure = { () in print(x) } } return closure } これのSILを出力すると
8:58 AM
foo1 と foo2 はほぼ同じになる。
8:58 AM
// foo1() sil @$s4test4foo1yycyF : $@convention(thin) () -> @owned @callee_guaranteed () -> () { bb0: %0 = alloc_stack $Int, var, name "x" // users: %3, %10, %4 %1 = integer_literal $Builtin.Int64, 1 // user: %2 %2 = struct $Int (%1 : $Builtin.Int64) // users: %8, %6, %3 store %2 to %0 : $*Int // id: %3 %4 = begin_access [read] [static] %0 : $*Int // user: %5 end_access %4 : $*Int // id: %5 debug_value %2 : $Int, let, name "x" // id: %6 // function_ref closure #1 in foo1() %7 = function_ref @$s4test4foo1yycyFyycfU_ : $@convention(thin) (Int) -> () // user: %8 %8 = partial_apply [callee_guaranteed] %7(%2) : $@convention(thin) (Int) -> () // users: %11, %9 debug_value %8 : $@callee_guaranteed () -> (), let, name "closure" // id: %9 dealloc_stack %0 : $*Int // id: %10 return %8 : $@callee_guaranteed () -> () // id: %11 } // end sil function '$s4test4foo1yycyF'
8:58 AM
// foo2() sil @$s4test4foo2yycyF : $@convention(thin) () -> @owned @callee_guaranteed () -> () { bb0: %0 = alloc_stack $Int, var, name "x" // users: %3, %14, %5 %1 = integer_literal $Builtin.Int64, 1 // user: %2 %2 = struct $Int (%1 : $Builtin.Int64) // users: %9, %7, %3 store %2 to %0 : $*Int // id: %3 %4 = alloc_stack $@callee_guaranteed () -> (), let, name "closure" // users: %10, %12, %13 %5 = begin_access [read] [static] %0 : $*Int // user: %6 end_access %5 : $*Int // id: %6 debug_value %2 : $Int, let, name "x" // id: %7 // function_ref closure #1 in foo2() %8 = function_ref @$s4test4foo2yycyFyycfU_ : $@convention(thin) (Int) -> () // user: %9 %9 = partial_apply [callee_guaranteed] %8(%2) : $@convention(thin) (Int) -> () // users: %11, %15, %10 store %9 to %4 : $*@callee_guaranteed () -> () // id: %10 strong_retain %9 : $@callee_guaranteed () -> () // id: %11 destroy_addr %4 : $*@callee_guaranteed () -> () // id: %12 dealloc_stack %4 : $*@callee_guaranteed () -> () // id: %13 dealloc_stack %0 : $*Int // id: %14 return %9 : $@callee_guaranteed () -> () // id: %15 } // end sil function '$s4test4foo2yycyF'
9:00 AM
クロージャのタイプは @convention(thin) (Int) -> () で一緒であって、 それに partial_apply de
Avatar
%8 = partial_apply [callee_guaranteed] %7(%2) : $@convention(thin) (Int) -> () // users: %11, %9
Avatar
キャプチャさせてる。
Avatar
x一個だからpartial applyするのがInt1個?
Avatar
だと思います。
Avatar
お、増やしたらちゃんと増えた
9:03 AM
SILの状態だとキャプチャ前の生関数とキャプチャ後のクロージャの型がちゃんと見えていて、partial_applyでちゃんと型の式になってるんですね
Avatar
手元でいろいろ遊んで勉強し直しました
1:30 PM
めちゃくちゃためになりました
1:30 PM
皆さんありがとうございます
Avatar
はじめまして。swiftサーバに最近参加したにーの( @n_shhhin )と申します。 今現在バックグラウンドで加速度を取得したい状況で、Background系の開発に疎いので手助けが欲しいです。AppStoreにリリースするのは目的ではないので、プロトでできればいい程度に思っています そこで質問なのですが、 iOS13で導入されたBackgroundTaskは BackgroundTask、 ●Background Processing Tasks - 数分かかる処理 - 延期可能なメンテ処理やCoreMLによるトレーニングを想定 ●Background App Refresh Tasks - 30秒のランタイム - アプリを最新の状態に保つための用途を想定 - performFetchのAPI が代わりにdeprecatedに みたいな感じの仕様らしいのですが、background processの数分ってのは実際どれぐらい処理が続く感じなんでしょうか。 また BackgroundTask では実現できないなら他の案をご教授いただきたいです。 既存アプリのGoogleフォトとかはバックグラウンドで常に写真のアップロードを監視してたりするのでできないことはないと思うのですが、どうやってバックグラウンドで常時処理をするのかが気になりました。よかったらどなたか強い人回答お願いします。 https://github.com/nshhhin/Background-Accel-Swift (edited)
バックグラウンドで加速度を取るプログラムSwift. Contribute to nshhhin/Background-Accel-Swift development by creating an account on GitHub.
Avatar
#beginner-help-archived にどうぞ
Avatar
すいません!ここは別枠のチャンネルなんですね!ありがとうございます
2:41 AM
selfキャプチャーでself.の省略、通った
2:42 AM
自分はRxSwift.Singleではselfキャプチャーしてるからだいぶコードがスッキリしそう
Avatar
Kishikawa Katsumi 11/27/2019 4:28 AM
これは [self] in ... と最初に書いておくとBodyで self.foo じゃなくて foo って書けるってものですよね?
Avatar
そうです〜
4:29 AM
nonescapingなクロージャでは従来も何もせずとも foo と書けたが、 escapingなクロージャにおいても [self]による明示的なself captureをすると、 同様にfooと書けるようになる。
Avatar
Kishikawa Katsumi 11/27/2019 4:34 AM
Proposalにも書いてあるとおりSwiftUIの記述がだいぶスッキリしますね。
4:35 AM
GeometryReaderで包んだらself書きまくらないといけないのがなくなるかな?
Avatar
return省略と同じでSwiftUIをスッキリさせたい気持ちを感じる
Avatar
Kishikawa Katsumi 11/27/2019 4:38 AM
まあOSがうまくやってくれてselfとか意識しないで済むならその方がいいですね。
Avatar
参照カウントだから意識するのはやめられない・・・
Avatar
Kishikawa Katsumi 11/27/2019 4:45 AM
呼ばれる方でうまくやってくれれば。。。SwiftUIはたぶん何も考えずにselfキャプチャしても(するしかない)大丈夫(?)だからそんな感じで。
Avatar
norio_nomura 12/4/2019 9:36 PM
In the master branch of the Swift compiler, we now have a first pass at cross-module optimization, allowing generic specialization across packages without manual @inlinable annotations! https://t.co/D0uM3PsNc1
Avatar
あるSwiftアプリでEXC_BAD_ACCESSでクラッシュして理由が表示されないのですが、Address Sanitizerをオンにするとクラッシュせずに実行できるようになります。どうやって原因を探ればいいでしょうか?
Avatar
omochimetaru 12/8/2019 5:14 AM
クラッシュしてるコードの行やその瞬間のコールスタックはデバッガでわかるので、 そこから、まずはどこでクラッシュしてるのかを調べます それでもわからなかったらその周辺のコードだけ新規アプリに持っていって、原因箇所と最小表現コードを探す それができたら自分のコードの問題なのかコンパイラのバグなのかわかる
5:16 AM
ASANが無効だと大丈夫ならわかるが、有効だと大丈夫だとすると、コンパイラが怪しい気もするけど
Avatar
ですよね。で、コールスタックなんですがクラッシュした行の次は0x00000000で終わってるんで、何も分からないです。サンプル作ってみても同じところでクラッシュします。ちなみにクラッシュするのは自作ライブラリの行で、SPMで導入したものがクラッシュして、ライブラリ内にあるサンプルプロジェクトではクラッシュしないという状態です。 (edited)
1:34 PM
コールバックじゃなくてコールスタック。
Avatar
サンプルプロジェクト見せてもらうことできますか?
Avatar
omochimetaru 12/8/2019 3:31 PM
SwiftPM限定ならSR-11564っぽいなあ。
Avatar
DEAD_CODE_STRIPPING = NOでいけました。ありがとうございます!
Avatar
omochimetaru 12/9/2019 1:59 AM
自分の場合、これを踏んだとき、RxSwiftのジェネリックなクラスを初めて使う時の、クラス生成の処理内部で落ちてる感じでしたが、
1:59 AM
コールスタックなんですがクラッシュした行の次は0x00000000で終わってるんで、何も分からない
これがどういう状態なのかわからず気になる
(edited)
2:00 AM
Xcodeのコールスタック表示は、ライブラリの部分を非表示にするモードがあるのですが、それで非表示になっている事はないですかね
Avatar
無いと思うんですが、どこ見たらいいですか?
Avatar
左のカラムの右下に青くなってるよく分からないボタンがあった気がする (edited)
Avatar
omochimetaru 12/9/2019 4:53 PM
明日動画上げますね
1:39 AM
@rizumita ↑こんな感じです
Avatar
閉じてました。が、開いてもクラッシュした個所の次は0 0x00000000で、そこまででした。
Avatar
なるほど・・・
8:19 AM
関数ポインタがnullだったとかなのかなあ。
Avatar
Hi Swift Evolution, Some holiday reading for you, a pitch of a new way of writing mutable computed properties and subscripts. For more information on the performance implications of this change and why it's an important feature to add, you might also find this talk from las...
6:22 PM
modify accessorのピッチ!コルーチンが来るぞ〜〜〜〜
Avatar
プロポーザルを見たときは、コルーチン中断時のクリンナップ制御にdefer使うのはクールだと思ったけど
1:32 AM
書き込み見てたら、非直感的で良くないなと思えてきた
Avatar
これが出来るようになると、RxSwiftのVariable(もうdeprecatedだけど)のlock機構とかがちょっと良くなりますね
Avatar
lock機構とは?
Avatar
コードだそうとしたけどもう完全に消えてるのかw
4:31 AM
Reactive Programming in Swift. Contribute to ReactiveX/RxSwift development by creating an account on GitHub.
4:32 AM
getとsetにlockが入ってるんですが、これだと値型のプロパティ変更で不整合が起きる可能性があるんですよね。_modifyならその可能性もなくなる。 (edited)
4:33 AM
variable.cat.age+=1 例えばこういうことが以前よりも安全に出来るようになる
Avatar
ふむふむ
4:52 AM
以前の不整合が起きる手順がわからないけど、 マルチスレッドとか自己の循環参照とかなら、 modifyになったところで同じように壊れる気もする
4:53 AM
modifyアクセサが排他せずに2個重ねて実行されて。
4:54 AM
あいや、ペアとなるget/setがまとめてmodifyの流れの中で頭とお尻でロックできるから
4:54 AM
今までと違うポリシーでロックできるのか。
Avatar
そうです
4:56 AM
get get set setが発生して壊れていたのが
4:56 AM
modify modifyにしかならなくなるので、安全
Avatar
なるほど〜
Avatar
omochimetaru 1/6/2020 12:32 AM
Allow payload-less enum cases to witness a static, get-only Self property protocol requirement. For example: protocol Foo { static var bar: Self { get } } enum Baz: Foo { case bar // Okay } Pa...
👀 2
12:32 AM
これ最近話題に出たやつだ。
Avatar
これ欲しい場面あったな
Avatar
これってこの後プロポーザルが挙がるんでしょうか?
5:21 AM
それとも今までの挙動がバグ扱い?
Avatar
omochimetaru 1/6/2020 5:23 AM
どうなんでしょーー
5:24 AM
バグチケットの方にまだ
5:24 AM
コアチームの見解が書いてないすね
Avatar
あっPRはごく最近できたのだったんですね
Avatar
norio_nomura 1/8/2020 12:49 PM
swift-5.2-DEVELOPMENT-SNAPSHOT-2020-01-06-aが出てる。
Avatar
omochimetaru 1/9/2020 5:10 AM
5:11 AM
型情報一切無いポインタなのにLLDBさんがそれがなんのwitness tableか教えてくれてる。
5:11 AM
シンボルテーブルと突き合わせてデマングルしてるのか?
5:12 AM
それともデバッグ用情報的なやつでわかるのか?
Avatar
シンボルテーブルと突き合わせて
これだと思います。image lookup -a でシンボル見えます
🙏 1
Avatar
omochimetaru 1/10/2020 5:47 AM
@Yuta Saito (lldb) image lookup -a 0x00007fff80870028 Address: libswiftCore.dylib[0x000000000039a060] (libswiftCore.dylib.__DATA_CONST.__const + 67528) Summary: libswiftCore.dylib`value witness table for Builtin.Int64
5:47 AM
ありがとう なんかできてそう
😋 1
Avatar
-vオプションつけるとデマングルされる前のシンボルも見えます (edited)
Avatar
omochimetaru 1/10/2020 6:02 AM
ああ、Summaryこれdemangleしてるだけか
Avatar
omochimetaru 1/10/2020 7:57 AM
Contribute to omochi/EquatableOpen development by creating an account on GitHub.
7:57 AM
できた〜
Avatar
omochimetaru 1/10/2020 9:24 AM
Linuxだとdlsymが動かない・・・
9:24 AM
# nm -a /usr/lib/swift/linux/libswiftCore.so | grep sSQMp 000000000043e484 R $sSQMp # nm -a .build/debug/EquatableOpenPackageTests.xctest | grep s13EquatableOpen0A6OpenerMp 000000000000d524 R $s13EquatableOpen0A6OpenerMp
9:24 AM
$sSQMp は見つけられるのに $s13EquatableOpen0A6OpenerMp が見つからない。
Avatar
dlsym、Xcodeでプロジェクト作っても動かなくなる場合がありますね
Avatar
omochimetaru 1/10/2020 9:25 AM
iOSはSwiftPM依存で取り込んだら動いたよ
Avatar
おお
Avatar
omochimetaru 1/10/2020 9:26 AM
swift_conformsToProtocolも大丈夫だなあ。なんか違う属性がついてるのかな。
9:27 AM
public protocol Equatable { /// Returns a Boolean value indicating whether two values are equal. /// /// Equality is the inverse of inequality. For any values `a` and `b`, /// `a == b` implies that `a != b` is `false`. /// /// - Parameters: /// - lhs: A value to compare. /// - rhs: Another value to compare. static func == (lhs: Self, rhs: Self) -> Bool }
9:27 AM
う〜む。
9:30 AM
# swift test -Xlinker -export-dynamic
9:30 AM
これでいけた
9:30 AM
I wrote a program to dlopen itself void hello() { printf("hello world\n"); } int main(int argc, char *argv) { char *buf="hello"; void *hndl = dlopen(argv[0], RTLD_LAZY); void (fptr)(void) = dlsym(
9:31 AM
Linuxでは実行ファイル自身を動的リンク可能にするにはリンカの指定が必要とのこと
Avatar
https://qiita.com/takasek/items/f51c26a8ee6a2929bb6e 昔書いた記事がいいねされて、こんなん書いたっけと思い出したんですけど decodeで明示的に型指定してるのを推論させるextensionなんですが、今振りかえってもやっぱり、別にこれでいい気がしてる なんか型推論に寄せることによる懸念を思いつく人いますか

デコード先の型を推論させたいという、ヒトなら誰しもが持つ欲望

@inamiy さんのスライド [Swift 4 Codable // Speaker Deck](https://speakerdeck.com/inamiy/sw...
Avatar
omochimetaru 1/12/2020 9:34 AM
ドーグの言う通り、「型推論は時々マジカルすぎる」というのはわかる
9:35 AM
型を解決するためには
9:36 AM
左辺か右辺の型がわからないといけないけど
9:36 AM
大体の場合は右辺から指定したい気持ちがある。
9:36 AM
これは評価順序と推論方向が一致してる方がわかりやすいから。
9:37 AM
で、タカセックの例だと
9:37 AM
大元のデコードは右から指定したいので推論拡張は不要で、、
9:37 AM
プロパティのデコードは、プロパティの型があるから左から推論できるんだけど
9:38 AM
そういう単純なパターンの場合はそもそもContainer操作を手書きしないで自動生成に寄せるべきだと思う
9:38 AM
自動生成に寄せられないようなややこしいケースがあるとしたら、そのときは右から推論させたい
9:39 AM
なので、良し悪し以前に利用シーンが個人的には無い気がする。
Avatar
そういう単純なパターンの場合はそもそもContainer操作を手書きしないで自動生成に寄せるべきだと思う
それは同意で、ただ部分的にできればいいんだけど、そうはいかないのが現状の問題かと 僅かな例外ケースのために、9割以上は単純なボイラープレートをひたすら書くことになる
Avatar
omochimetaru 1/12/2020 9:40 AM
どんなケース?
Avatar
struct Hoge: Decodable { ... (10個くらいある単純なプロパティ) let isIPhone: Bool }
9:43 AM
ちがうな、これだとCodingKeysでいいか
Avatar
1個でもカスタムにすると全部書くことになると思うのだけど
Avatar
そう、そのこと
Avatar
omochimetaru 1/12/2020 9:44 AM
そういうときは
9:45 AM
そのカスタムしてるエンコード方法に対応するstructを一つ作った上で
9:45 AM
自動生成用の型を別に作ってる
9:45 AM
で、自動生成用の型と、元々のモデル型の間の変換だけ書いたら
9:46 AM
Codableになるようにプロトコルを使ってる。
9:46 AM
Contribute to omochi/WeaselRoll development by creating an account on GitHub.
9:47 AM
↑利用側のコードが上がってないから説明不足になるけど、そのプロトコルはこれ
9:47 AM
プロパティごとにContainerのコードを書くよりは
9:47 AM
init(fromCodableProxy proxy: CodableProxy) throws
9:47 AM
を実装する方が、意味の露出が少なくて安全だし
9:48 AM
記述量がすくない
Avatar
例えばカスタムデコーダーをどうしても書きたい(手書きになる)みたいなケースが、例えばenumとかでよくあるんだけど
9:52 AM
或いはUInt64はiOS10でバグるのでどうしても手書きが必要、とか (edited)
9:52 AM
まあその辺では左辺が型を決定しているのでselfで埋めて貰えると助かるな、というのはわかる
Avatar
omochimetaru 1/12/2020 9:52 AM
type名で分岐するパターンはちょっと書くことになるね
Avatar
そうそう おもちさんのはこれはこれで興味深いけどちょっと解決したいものが違う
Avatar
omochimetaru 1/12/2020 9:53 AM
enumのassociatedValueに直接decodeする場合はまあ左からの推論になるか。
9:55 AM
そういう時は使うメリットはあると思う レアケースだから右に型書いて不便は無いけど
9:55 AM
ドーグが言うマジカルなケースは
9:55 AM
その通り時々なので
9:55 AM
そもそもそういう、まずい使い方に関しては
9:56 AM
俺は、まずい使い方はしなければ良い派なので、
9:56 AM
正しく使う前提で便利だとは思うよ。
9:57 AM
なんかリテラルとかガチャガチャ絡めた式でいつのまにかIntからFloatにかわっちゃって壊れる とかがあるんじゃない? そういうところでは右に書けと思う
Avatar
うーん、そもそもそういうケースではambiguousになるはずなので
Avatar
omochimetaru 1/12/2020 9:58 AM
そうとは限らないよ
9:58 AM
1を1.0に書き換えちゃうとか。
Avatar
"""{ "a": 1 }""" struct A { let a: Int }"""{ "a": 1.0 }""" struct A { let a: Int } に書き換わるって話?
Avatar
var foo = try decode(from: json) + 1 こういう無茶苦茶な推論が通るのはちょっと…というのはまあわからんでもない
Avatar
タルノンの例だね 1.0にかきかわるって言ったのはSwiftコード側の話
10:01 AM
そうそう。そういう変な書き方ができるのは後でややこしい壊れ方をするかも?ぐらい。
10:01 AM
まあ変なコードはいくらでも錬成できると思う
Avatar
左辺で型が決まらないケースなら右辺に明示したいのはよくわかる
10:03 AM
でもたいていの場合は左辺が型決めてるでしょdecodeって
Avatar
左辺で決まっていないにも関わらず右辺のリテラルから推論できちゃう、というのは何か別の問題な気がしていて
Avatar
そこの、たいてい、には同意できないという事。
10:03 AM
そのたいていのケースは手書きしない方に解決できるから。
Avatar
それをType引数のデフォルトを否にするのと絡めてるのはあんまり良くない肝
Avatar
右辺のリテラルから決まるのは足し算の引数の合流から決まってるから
10:05 AM
左とも右とも呼びづらいなw
10:05 AM
隣?
Avatar
型推論的にはdecodeから見たら左が決定してそう
Avatar
まあコンテキスト的に決まってるという意味では左だけども
10:06 AM
そだね
10:06 AM
use position側からきまっとる
10:08 AM
たかせく自身が「ボイラープレート」でたくさん書くって主張してるけど
10:08 AM
ボイラープレートをたくさん書いてる場合はまずそれを最小化した後で
10:08 AM
議論すべきだと思う
10:10 AM
タルノンの言う
10:11 AM
enumの分解をたくさん書いてる話も
10:11 AM
EitherJSON3<A,B,C>みたいな型を一度作れば
10:11 AM
Container操作は再利用できる気がする。
Avatar
ボイラープレートをたくさん書いてる場合はまずそれを最小化
うーん、この手段が見えてない DecodableProxyがその解決策になってる気がしないんですよね コード全体が見えてなくてぴんときてないのかもだけど
Avatar
後で例を出しますね
Avatar
あとおもちさんのHasDecodableProxyは他にも(あるいは他じゃないのかもしれないけど)引っかかるところがあって、 3層レイヤードアーキテクチャ View - Model - Infra 層があったとして、 CodableProxyはInfra層のDTO HasDecodableProxyはModel層のDomainObject になると思っていいかな そうすると、 1. 依存の方向を Model <- Infra にしたいけど、HasDecodableProxyの構造だとそれができない 2. CodableProxyがひとつに固定されてしまう という問題がある

依存の方向を Model <- Infra にしたいけど、HasDecodableProxyの構造だとそれができない

雑に言えばmemberwise initializerがinternalになるのと同種の問題だと思ってよくて、 DTOをInfra層に閉じ込めようとするとHasDecodableProxyをInfra側にextensionで書くことになる そうするとDomainObjectのpublic memberwise initializerを手で書かにゃならん DomainObjectにプロパティがたくさんあった場合、
  • public memberwise initializer
  • init(fromCodableProxy proxy: CodableProxy)
を手作業で書きまくって、それぞれをメンテしなきゃいけないの気が遠くなりそう

CodableProxyがひとつに固定されてしまう

明確な問題はたとえばCatを取得したくて、 V1 APIとV2 APIでレスポンス構造が変わるけどどちらもクライアントでは同じCatとして扱いたい そうすると以下のようになると思うんだけど CatDTOV1: { id: Int, name: String, ownerID: Int, ownerName: String, ... } CatDTOV2: { id: Int, name: String, owner: Owner, ... } struct Cat: HasDecodableProxy { typealias CodableProxy = CatDTOV1??CatDTOV2?? } このときassoctypeとしてProxyはV1かV2かどっちかひとつに固定されるのはきつくない?
(edited)
Avatar
そういう場合は Model層のDomainObjectとしてのCatと、
10:51 AM
V1APIのCatと、V2APIのCatは別の型にしている。
10:52 AM
V1APIのCatの中で、Codable実装のためだけに、CodableProxyを使う。
10:52 AM
CodableProxyはInfra層のDTO HasDecodableProxyはModel層のDomainObject
両方ともDTOということ。
10:54 AM
public struct PlayerM: HasCodableProxy { public var trackingID: String public var id: Player.ID public var x: Float public var y: Float public var distance: Float public var speed: Float public var position: GLKVector2 { GLKVector2(x, y) } public struct CodableProxy: Codable { public var id: String public var no: Player.ID @FormatCoding<FloatStaticFormatter> public var x: Float @FormatCoding<FloatStaticFormatter> public var y: Float @FormatCoding<FloatStaticFormatter> public var distance: Float @FormatCoding<FloatStaticFormatter> public var speed: Float } public init(trackingID: String, id: Player.ID, x: Float, y: Float, distance: Float, speed: Float) { self.trackingID = trackingID self.id = id self.x = x self.y = y self.distance = distance self.speed = speed } public init(fromCodableProxy p: CodableProxy) { self.init(trackingID: p.id, id: p.no, x: p.x, y: p.y, distance: p.distance, speed: p.speed) } public func encodeToCodableProxy() -> CodableProxy { CodableProxy(id: trackingID, no: id, x: x, y: y, distance: distance, speed: speed) } }
10:56 AM
↑最近のだとこんなの @FormatCoding<FormatStaticFormatter> は Floatを %.2f 書式の 文字列としてエンコードする型
10:56 AM
public struct CameraCalibration: Codable { public typealias JSON = [CameraCalibration] public var fov: Float @ColumnMajorFloatArray9Coding public var rotation: GLKMatrix3 @FloatArray3Coding public var translation: GLKVector3 public init(fov: Float, rotation: GLKMatrix3, translation: GLKVector3) { self.fov = fov self.rotation = rotation self.translation = translation } }
10:57 AM
↑こっちはCodableProxyは使ってないけど、 @FloatArray3Coding などが、3次元ベクトルを 3要素Float Array にエンコードする型
10:57 AM
ちょっと手元のテクニックが移行期で、PropertyWrapperを使うことによってCodingProxyが不要になりつつある・・・
10:58 AM
public struct PlayerSpecifier : HasCodableProxy, Hashable { public struct CodableProxy : Codable { public var teamID: Team.ID public var teamColor: ColorProxyRGB public var playerID: Player.ID public var name: String } public var teamID: Team.ID public var teamColor: Color public var playerID: Player.ID public var name: String public init(teamID: Team.ID, teamColor: Color, playerID: Player.ID, name: String) { self.teamID = teamID self.teamColor = teamColor self.playerID = playerID self.name = name } public init(fromCodableProxy p: CodableProxy) { self.init(teamID: p.teamID, teamColor: p.teamColor.value, playerID: p.playerID, name: p.name) } public func encodeToCodableProxy() -> PlayerSpecifier.CodableProxy { return CodableProxy(teamID: teamID, teamColor: ColorProxyRGB(teamColor), playerID: playerID, name: name) } }
10:59 AM
↑こっちは1世代前のコードでわかりやすいと思う ColorProxyRGB が Color型を Float3要素Array にコーディングするための型
Avatar
PlayerMやPlayerSpecifierは、InfraかModelかでいうとどちら?
Avatar
PlayerMは完全に通信プロトコル固有のやつだから、
11:01 AM
Infraになるのかな?(DDD詳しくない)
11:01 AM
PlayerSpecifierはInfraとModelどっちも共通(そのままで済んだ
11:01 AM
PlayerMとは別にモデルとしてのPlayerは別にある。
11:02 AM
(1つめと2つめのコードが最近のプロジェクトSで、3つめのコードは別のプロジェクトJ
Avatar
なるほど Playerに新たなプロパティhogeを増やす場合、
  • Player.hoge
  • Playerのmemberwise initializer
  • PlayerM.hoge
  • PlayerM.CodableProxy.hoge
  • PlayerMのmemberwise initializer
に改修が入る?
Avatar
その5つはそう、それに加えて、 PlayerMのinitFromCodableProxyとencodeToCodableProxyもだね。
11:05 AM
ただ、Player.hogeに改修を加えた時点で、他の6つは全部連鎖的にコンパイルエラーが出るので漏らすことは無い。
11:05 AM
DecodingContainerを触るコードを書く場合の致命的な問題点として、 Decode処理とEncode処理の対称性が静的に保証できないという事があると思ってて
11:06 AM
Decode側で追加したのと対になるロジックをEncode側にも書かないと、 EncodeしたときはJSON表現が違うとか、Encode側に追加をわすれて、保存すると消えちゃうみたいなバグが出る
11:07 AM
このスタイルだとJSONとのマッピングは常に自動生成に頼ってるのでそういう事故がない これはボイラープレートの手書きを回避したからって事だと思ってる
Avatar
Decode処理とEncode処理の対称性が静的に保証
そこの解決策としてのありがたさはよくわかった
11:12 AM
ただ、やっぱりそもそもの「ボイラープレート」で意図してるところが違ってるんだな
11:16 AM
ぼくがボイラープレートって言ったのは、 プロパティ1つにつき上記7箇所の本質的ではないコードを自分で書かなきゃいけないってこと プロパティが10個あったら70箇所 それをボイラープレートと言った それはCodableに則って init(from:)encode(to:) を書く場合には1つになるけど、 それでもプロパティ10個あったら10行の非本質的なコードが発生する その中で、左辺で型が分かりきってるのに右辺にも型を書かなきゃいけないってのは、 さらにげんなりする 右辺から型を省略可能になれば、焼け石に水ではあるけど少しはマシになるんじゃないの? というのが今回言いたかったこと
Avatar
CameraCalibration
の例だと数が同じにならない?
11:19 AM
CodableProxyでやりたかった事がPropertyWrapperで解決してるんだよね
11:20 AM
同じというか減ってる気がする
Avatar
CameraCalibrationはPropertyWrapperがなくてもinit(from:) encode(to:) を書かずに済むので、それは話が発散する
Avatar
いや、そこは発散じゃなくて同じ話だと思う
11:25 AM
ボイラープレートになるようなCodingContainerの操作は
11:25 AM
単純故に自動生成に寄せられるはずだから
11:25 AM
そもそもそういうケースは減らせるはずというのが僕の主張で
11:25 AM
CodableProxyはその実例だけど、ただ、別種のボイラープレートが増えちゃうから良し悪しが出ちゃうと
11:25 AM
でも PropertyWrapperによる解決だったら、ボイラープレート数が増えてはいないので
11:26 AM
もともとの主張のより強い根拠になってる。
11:30 AM
まあ、「自動生成に寄せられる」が否だったとして
11:30 AM
その中で、左辺で型が分かりきってるのに右辺にも型を書かなきゃいけないってのは、 さらにげんなりする
これはわかる。
11:31 AM
「左辺の型がプロパティの型として決まってて、右辺がボイラープレートになる」これがまさに自動生成できる要件が整ってる事を言ってるような気もするけど・・・
11:31 AM
「ボイラープレートを手書きしないといけないなら推論が効いて楽な方が良い」はまあ正しいと思います
11:33 AM
もともとのそれをやる問題点のトピックに関しては、変なコードを書いた場合に混乱しうるという観点はあるが、提案してるシナリオだとそれは踏まないしね。
Avatar
>PropertyWrapperによる解決だったら、ボイラープレート数が増えてはいないので JSONのプロパティとModelのプロパティが1:1に定まる、という条件ならおもちさんの話は通る JSONを単純に型付けしたDTOを作って、そこからModelに投射するというのも良い案だし、 「CatV1, V2をCatDTOにしてからCatを作る」という例はむしろそのアプローチが最大に活きるパターン
11:37 AM
それでも、DTOを噛ませずContainerから直接作りたいと思うことはけっこう自分はあって、たぶんその状況が普段生まれるか生まれないかが視点の違いになってると思う
11:43 AM
要は、何層もネストしたDTOのコンバートってキツいよねってことなんだけど { a: { b: { c: { d: { e: { x: "", y: "", z: "", i: 1 }}}}}} { a: { b: { c: { d: { e: { x: "", y: "", z: "", b: true }}}}}} Eの中身の一部が、場合によって変化するとします EにDTOを噛ませる場合、連鎖的にD,C,B,AもDTOを噛ませなきゃいけない 同じ構造の型を作るの辛い だったらEには init(from:) を書いて、全部素のDecodableにしたい そのとき、x,y,zが変わらないのはわかりきってるのに、そこでも右辺にも型指定しなきゃいけないのはめんどい (edited)
11:46 AM
こういったデコードが多く発生するプロジェクトだと、Containerの扱いの細かい部分が気になってくるわけです 逆に、JSON色付け係ばっかでEncodableが出てくることはほぼなかったので、 そこをCodableProxyで解決できるんだって言われても有難みがあんまり気にならない (edited)
Avatar
あー
11:54 AM
構造の深堀りを型を使わずにcontainerでゴリゴリ書いちゃうって事?
11:56 AM
CodableProxyにせよ、PropertyWrapperにせよ、ABCDはそのままで、Eだけ改造することはできますよ。
11:56 AM
逆に、JSON色付け係ばっかでEncodableが出てくることはほぼなかった
Encodableが出てこない、なるほど・・・
11:59 AM
あいや、あれか、API用のデコードを別にしようとすると
11:59 AM
ABCDをデフォルトにできない?
Avatar
あーそうか、 init(fromCodableProxy:) 呼んでるのは init(from:) の中か https://github.com/omochi/WeaselRoll/blob/master/Sources/WeaselRoll/Codable/CodableProxy.swift#L16
Contribute to omochi/WeaselRoll development by creating an account on GitHub.
Avatar
そうそう。
Avatar
たしかにこれで解決だ
Avatar
ABCDがややこしいのはAPI固有のほうの話だから、そうだよね
Avatar
終  制作・著作  ━━━━━   ⓃⒽⓀ
Avatar
たしかにこれで解決だ
そこの誤解があったか
Avatar
Decoderを使って得られるのがDTOで、そこからModelにマップしてやらなきゃいけないって前提で喋ってた
12:03 PM
Decoder使ったら直でModelが得られるならそれで全然いい
12:04 PM
だから HasDecodableProxy : Decodable なのか
4:25 PM
extension MyProto { dynamic func myMethod() { print("Protocol method") } } struct NoOverride: MyProto {} struct HasOverride: MyProto { func myMethod() { print("Struct method") } } func call_generic<T: MyProto>(_ object: T) { object.myMethod() } let defaultObject = NoOverride() defaultObject.myMethod() // "Protocol method" call_generic(defaultObject) // "Protocol method" let object = HasOverride() object.myMethod() // "Struct method" call_generic(object) // "Struct method" <-- This.
4:25 PM
protocol requirementsではない場合にでもprotocol extensionをdynamic funcにするとdynamic dispatchになるという仕様の提案
4:25 PM
実装できなくね?とオモタ
Avatar
switch からループを break できると思って↓のようなコード書いてしまった・・・。 @swift-5.1.5 for i in 1...10 { switch i % 5 { case 0: print("end") break default: print("\(i)") } }
Avatar
1 2 3 4 end 6 7 8 9 end
Avatar
正しくは↓。 @swift-5.1.5 loop: for i in 1...10 { switch i % 5 { case 0: print("end") break loop default: print("\(i)") } }
Avatar
1 2 3 4 end
Avatar
普段 casebreak 書かないから必要ないものと認識されてて外側のループに作用するように思ってた。
2:07 AM
casebreak 必要だからしかたないのか
2:08 AM
あ、↑のコードは if でいいけど、実際のコードは exhaustive に switch で分岐したいケース。
Avatar
「何もしない」が表現できればそれでも良い気はしますね
Avatar
ですねー。なんかせっかく break から開放されたと思ってたらまだ C に引きずられてて気持ち悪い感じ。
2:14 AM
でも、昨日初めて(ではないかもしれないけど数年ぶりに?) fallthrough が必要なコードを書いたし、仕方ないのかな・・・。
Avatar
omochimetaru 1/19/2020 5:39 AM
breakはswitchに吸われるけどcontinueはforに吸われるので
5:39 AM
switchの後ろにbreakを書きつつ、not endのcaseでcontinueを書くと
5:40 AM
ラベル不要にw
Avatar
げー、 breakcontinue でそこ揃ってないのか・・・。
Avatar
omochimetaru 1/19/2020 7:29 AM
そう。その特性うまく使うとおしゃれに書けることあるけど、ややこしい
Avatar
揃えたとするとcontinueはfallthrough相当の動きをするべきなのかな
Avatar
omochimetaru 1/21/2020 1:47 AM
switch/for/continue/breakはC系で全部同じ動きするから
1:47 AM
fallthroughになるのはやばそう
1:48 AM
やるとすると書くのを禁止するしかないんじゃないか
Avatar
Kishikawa Katsumi 1/21/2020 4:45 AM
switchが下に抜けないようにした時点でbreakはswitchじゃなくて外側に作用するようにしてたら良かったと思うな。 今となってはしょうがないけど。
Avatar
omochimetaru 1/21/2020 4:47 AM
あ〜外側に揃えるのか。
Avatar
それがベストな気はしますね、switchの中で挙動のコントロールはfallthroughだけになる
Avatar
Kishikawa Katsumi 1/21/2020 4:47 AM
switchにbreak書く意味はないからbreakはswitchに作用しなくて外側にループがあったら抜ける。
Avatar
omochimetaru 1/21/2020 4:48 AM
確かにif文にもbreakは無いしswitchだけ途中で終われる事のほうが変な感じだ。 (edited)
Avatar
Kishikawa Katsumi 1/21/2020 4:48 AM
switchがfallthroughしない他の言語はどうなってたかなと思ったけど、Goもラベル付きbreakですね。こういう場合は。
4:48 AM
他の言語はよく知らない。
Avatar
その場合空caseに何か必要なのでは?
Avatar
omochimetaru 1/21/2020 4:48 AM
空case 別によくねって思う。
Avatar
Kishikawa Katsumi 1/21/2020 4:49 AM
空ケースに書くのはセミコロンとか()でいいんじゃないですか
Avatar
omochimetaru 1/21/2020 4:49 AM
何も書かなくても特に曖昧性ないですよね?
Avatar
Kishikawa Katsumi 1/21/2020 4:49 AM
空で書けてもいいと思います。
Avatar
そうですね。下にfallthroughしそうな見た目だと思ったんですがswiftが明示的なfallthroughを要求することを知っていれば大丈夫か。
Avatar
omochimetaru 1/21/2020 4:57 AM
Swiftのその辺の文法はC系(Objective-Cもか)からの移行コストを減らす事にだいぶ寄せているなあ
Avatar
Kishikawa Katsumi 1/21/2020 4:59 AM
Rustから借りてきて match みたいな文にして今のswitchをなくすか徐々に使われなくしていってもいいのかもしれない。
Avatar
Kishikawa Katsumi 1/21/2020 12:49 PM
class ViewController: UIViewController { let processingQueue = DispatchQueue(label: "com.kishikawakatsumi.test") override func viewDidLoad() { super.viewDidLoad() processingQueue.async { [weak self] in self?.processingLoop() } } private func processingLoop() { while true { // Do something } } } ^ これでDispatch QueueがViewControllerの参照を持ち続けてしまうためにViewControllerが解放されないの、直す手段ありますか?
12:50 PM
while true のところを変数にして while isProcessing とか 閉じるタイミングなどで外からそのフラグをfalseにする、くらいしか思いつかなかった。
Avatar
ループが自身の参照持ってるんでこうなるのは正しそう
12:53 PM
とりあえず
12:53 PM
class ViewController: UIViewController { class Process { let processingQueue = DispatchQueue(label: "com.kishikawakatsumi.test") weak var parent: ViewController? init(parent: ViewController) { self.parent = parent } func run() { while let parent = parent { } } } lazy var process = Process(parent: self) override func viewDidLoad() { super.viewDidLoad() process.run() } }
12:54 PM
メモリリーク避けつつ開放されたら止まるようにもしてみました。
Avatar
フラグなりなんなりで分岐してループ抜ける必要がありますね
Avatar
Kishikawa Katsumi 1/21/2020 12:59 PM
たるのんさんのやつ、なんか違くない? これだと process.run() で無限ループに入って出てこなくなってしまう。
Avatar
あwDispatchQueue使うの忘れてました
1:00 PM
よしなに補完してくだされ〜
1:00 PM
高階関数にすればクラス使わなくてすみそうな気がしてきた
Avatar
Kishikawa Katsumi 1/21/2020 1:01 PM
class ViewController: UIViewController { class Process { let processingQueue = DispatchQueue(label: "com.kishikawakatsumi.test") weak var parent: ViewController? init(parent: ViewController) { self.parent = parent } func run() { while let parent = parent { } } } lazy var process = Process(parent: self) override func viewDidLoad() { super.viewDidLoad() process.processingQueue.async { [weak self] in self?.process.run() } } }
1:02 PM
こうですね!無限ループの条件がselfがあるかどうかだからいいのか。
Avatar
runの中でasyncした方がちょっとだけ綺麗かな
1:02 PM
クラスいらないやつ書いてるので暫しお待ち
1:07 PM
class ViewController: UIViewController { let processingQueue = DispatchQueue(label: "com.kishikawakatsumi.test") override func viewDidLoad() { super.viewDidLoad() processingLoop { (self) in print(self) } } func processingLoop(_ f: @escaping (ViewController) -> ()) { processingQueue.async { [weak self] in while let strongSelf = self { f(strongSelf) } } } }
1:07 PM
できたできた
1:08 PM
while letで弱参照をループごとに引っぺがすことで、永続的なretainを持たないことがミソですね! (edited)
Avatar
Kishikawa Katsumi 1/21/2020 1:09 PM
なるほど?
Avatar
Kishikawa Katsumi 1/21/2020 1:21 PM
うーんなるほど。これはすごいですね。
1:21 PM
while let ... じゃないと書けないんですよね?
Avatar
while文でoptional bindingしてるだけで
1:22 PM
本質的には while true { guard let self = weakSelf else { break } } に同じです
1:23 PM
ループの中に弱参照持ち込むところだけできればどんな書き方でもオッケー
Avatar
Kishikawa Katsumi 1/21/2020 1:25 PM
あ、ホントだ。いろいろ書き換えてて、while letじゃないと(=たるのんさんのやつじゃないと)うまく言ってなかったんですけど、while true {とguardでもできました。
1:25 PM
完全に理解しました。どうもありがとうございます 🙏🏻😊
👍 1
Avatar
omochimetaru 1/21/2020 1:31 PM
extension DispatchQueue { func startBindingLoop<T: AnyObject>(_ object: T, _ f: @escaping (T) -> Void) { weak var object = object self.async { while true { guard let object = object else { break } f(object) } } } } class ViewController { let pq = DispatchQueue(label: "pq") func viewDidLoad() { pq.startBindingLoop(self) { (self) in print(self) } } }
1:32 PM
パターンの再利用可能版↑
Avatar
Kishikawa Katsumi 1/21/2020 1:36 PM
良さそう。
Avatar
omochimetaru 1/21/2020 1:40 PM
class ViewController { class Task { var param: Int = 3 func run() { print(param) } } let pq = DispatchQueue(label: "pq") var task: Task? func viewDidLoad() { let task = Task() self.task = task pq.startBindingLoop(task) { $0.run() } } func viewWillDisappear() { task = nil // stop task } }
1:40 PM
↑こんな風に止めたりできて便利かもしれませんね
1:43 PM
ただまあ、元のコードにしても、 ViewControllerがnilになった後も、 「BG処理の次のループが開始しない」 だけであって、 nilになった瞬間に開始していた周回の処理が割り込まれて止まるわけではないので、 「ViewControllerはnilだけどBG処理が実行されている」 時間帯が発生しうるので、その状況でエンバグしない考慮は必要ですね。
1:44 PM
「BG処理の実行中はVCがdeinitされていない」事は保証されてるけど。
Avatar
OptionalBindingしたらループ抜けるまで最低でもretainCount=1にならないんでしたっけ?
Avatar
omochimetaru 1/21/2020 1:47 PM
最低1はあるからdeinitはしない。
1:47 PM
ただ、もともと想定してたほうのVCを持ってる最後の変数がnilになっても、 そっちのループ側が残るからVCが解放(deinit)はされてないけど、UIKit上は完全に消えてる時間帯が生じる (edited)
Avatar
それはそうだね
Avatar
Kishikawa Katsumi 1/21/2020 1:50 PM
実際にはこれはループの中ではマイクからの音を処理していて、 波形を描くための情報をループごとにモデルにPublishする、というものです。 Viewが閉じたあとにコールバックが呼ばれても無視するようにしておかないといけないってことですね。
Avatar
omochimetaru 1/21/2020 1:52 PM
そうですね。 コールバックが呼ばれている「最中」でさえ、Viewが閉じる可能性がありますね。 モデルにPublishするところとか、モデルからUIに流し込まれるところで、なんかチェックしておけば大丈夫そう
Avatar
安全な設定APIみたいなのを型システムでつくりたい的な話題はどのチャンネルでしょうか...? ここかな?
Avatar
ここだと思います
Avatar
enum Valid {} enum Invalid {} struct Configurable { let configuration: Configuration<Valid, Valid> } struct Configuration<FlagA, FlagB> { private var a: Int? func setFlagA(a: Int) -> Configuration<Valid, FlagB> { return Configuration<Valid, FlagB>(a: a, b: b) } private var b: String? func setFlagB(b: String) -> Configuration<FlagA, Valid> { return Configuration<FlagA, Valid>(a: a, b: b) } } func noConfiguration() -> Configuration<Invalid, Invalid> { return Configuration() } let configuration = noConfiguration() .setFlagA(a: 1) .setFlagB(b: "b") Configurable(configuration: configuration)
12:34 AM
一応あるていど期待通りなんですが、なんかイマイチ感があって。
12:35 AM
似たような感じの知られてる実装があったら知りたいと思いました。
Avatar
omochimetaru 1/22/2020 1:31 AM
僕が知ってるのもそんな感じですねえ。
Avatar
各プロパティが Optional である必要はなさそうに思います。
Avatar
omochimetaru 1/22/2020 1:49 AM
未設定の状態が維持できなくないですか? 型を変えようとすると、設定手順の組み合わせ爆発しちゃうし
Avatar
Optionalなのは隠せるので、まあ...
2:12 AM
なんというか Scala でいうところの Nothing がないので、若干冗長なことが多いです。何かを入れなきゃいけないので。
Avatar
omochimetaru 1/22/2020 2:14 AM
Never が似たような役割を果たす場面もありますよ
Avatar
Valid か Invalid で未設定の管理しているわけで、初期値が0とか""みたいにtrivialに入れられるのであれば、いらなくないです?
Avatar
omochimetaru 1/22/2020 2:16 AM
初期値なるほど
Avatar
そうかも。
2:17 AM
プロミティブなやつらだけならそうですね。
Avatar
Invalid の代わりに Never でもいいですね。
Avatar
Scala でいうところの Nothing がないので、若干冗長なことが多いです。
これって、たとえば Never 使っても enum Invalid {} の一行がいらないだけでに思えるんですけど、 Scala だとどういう冗長さをなくせるんですか?
Avatar
nitpickですが Configuration<Int, Int>() とか作れちゃいますね。
Avatar
Scalaだと、Generics のデフォルトがNothingなので
😮 1
3:29 AM
書かなきゃNothingになるんです
🙏 1
Avatar
なるほど。
Avatar
protocol Condition {} enum Valid: Condition {} enum Invalid: Condition {} にして FlagA: Condition... とかにすれば Int とか作られなくなりますけどまあ、作りたかったら作っても良いのでは的な気持ちも
3:32 AM
noConfigutation() とかいらなくて Configuration() みたいにかける感じです > Nothing (edited)
Avatar
extension Int: Condition で回避されそうですね・・・。
3:34 AM
protocol は隠せないからなあ...
Avatar
@koher さすがにそこまでは面倒見きれないですねぇ
Avatar
sealed が要りますね。
Avatar
sealed trait みたいなのがないから enum で回避したことを思い出した
Avatar
あー、 public class Condition にして、サブクラスをモジュールに閉じ込めれば( open でないと外部から継承できないので)できるかも・・・。
3:38 AM
noConfiguration については、↑の話を聞くまでは、 Configuration<Int, Int> とかを防止するために、 Configuration のイニシャライザは本来 fileprivate にして外部から隠蔽して、 noConfigurationsetFlag 経由でしかインスタンス生成できないようにするためのものかと思ってました。
Avatar
なるほど。あんまり隠すことは丁寧に考えてなかった...
Avatar
Configuration<Int, Int> は問題ないけど、 Configuration<Valid, Valid> を勝手に作られたら、型で守っても壊されそうです・・・。
Avatar
そんなの作らないで >_<
😅 1
5:14 AM
いやでもクリティカルな指摘だと思います。正しく隠蔽する必要性は高いですよね。
Avatar
omochimetaru 1/22/2020 5:24 AM
目的の種類が違うんで状況次第だと思います
5:24 AM
正しく隠蔽するのはわからない人もそれを使う場合には大事だけど わかってる本人にとってヒューマンエラーを減らすための仕組みにも価値があって、その範囲だと隠蔽はいらない
Avatar
個人的なきもちとしては設定APIのパターンとして蓄えておきたいので、ある程度の考慮はしておきたいなと思ってました。
Avatar
omochimetaru 1/22/2020 5:44 AM
なるほど
Configuration のイニシャライザは本来 fileprivate にして外部から隠蔽して、 noConfiguration と setFlag 経由でしかインスタンス生成できないようにする
これをやっておけば
Configuration<Valid, Valid> を勝手に作られたら
↑Valid, Validのインスタンスは勝手に作れない気がする
Avatar
Builder にしておいたほうが、使用側の利便性はよさそうと思いました enum Valid {} enum Invalid {} struct Configurable { let configuration: Configuration } struct Configuration { fileprivate init(a: Int, b: String) { self.a = a self.b = b } let a: Int let b: String } struct ConfigurationBuilder<FlagA, FlagB> { private var a: Int = 0 func setFlagA(a: Int) -> ConfigurationBuilder<Valid, FlagB> { return ConfigurationBuilder<Valid, FlagB>(a: a, b: b) } private var b: String = "" func setFlagB(b: String) -> ConfigurationBuilder<FlagA, Valid> { return ConfigurationBuilder<FlagA, Valid>(a: a, b: b) } private init(a: Int, b: String) { self.a = a self.b = b } } extension ConfigurationBuilder where FlagA == Invalid, FlagB == Invalid { init() {} } extension ConfigurationBuilder where FlagA == Valid, FlagB == Valid { func build() -> Configuration { return Configuration(a: a, b: b) } } let configuration = ConfigurationBuilder() .setFlagA(a: 1) .setFlagB(b: "b") .build() _ = Configurable(configuration: configuration) (edited)
💯 1
Avatar
omochimetaru 1/22/2020 6:03 AM
Builderだとデフォルト値が取れないような型があっても、Builder内部にだけOptionalで持たせて、Productの型はnon-optionalにできて良いですね (edited)
Avatar
昨晩はお布団に吸い込まれてしまったが、extensionwhere つかうと implicit をつかった evidence みたいなのができる確かに、と思った。これだとかなり Scala のパターンに近いレベルになってる。素敵。
Avatar
The Swift project has achieved a critical milestone of maturity of the core fundamentals, providing stability for users to invest in using Swift in earnest. On Apple's platforms such as macOS and iOS, the arrival of ABI and module stability has enabled the creation of stable...
11:44 PM
Swift6の方向性がアナウンスされた!
11:49 PM
concurrency, ownership、あとcompnerdさんがコアチーム入りだって
11:50 PM
windows版公式サポートに進むかな?
Avatar
omochimetaru 1/23/2020 1:28 AM
variadic genericsも書いてあるし期待
1:34 AM
tkremenek I suspect that Swift 6 will not push generics features "to their limits", but I do suspect that some work in this area will be prioritized especially where there is a compelling need that will empower users to write better APIs. For example, I mentioned variadic generics in my post.
1:35 AM
このbetter APIのためのvariadic generisってSwiftUIのTupleView<...> の事意識してると思う
Avatar
Kishikawa Katsumi 1/23/2020 10:57 AM
https://twitter.com/objcio/status/1219998374352629760?s=21 型推論は難しいな。間違えたわ。
// Swift Quiz // by @tammofreese func foo() throws -> Int { 0 } func foo() throws -> Int? { 1 } let a = (try? foo()) let b = (try? foo())! let result = (a == b) // What’s the value of result? (Swift 5)
Avatar
やってみた、あってた。
Avatar
Kishikawa Katsumi 1/23/2020 1:51 PM
さすが。これtry?がついてるのが難しいですよね。
Avatar
omochimetaru 1/23/2020 2:07 PM
あれ?勘違いしてたな なんで正解したんだ
2:10 PM
結果的にresultの値と呼び出されるfooは思ったとおりだけど、全然わかってなかった
2:12 PM
func goo() throws -> Int? { 1 } let a = try? goo() print(type(of: a)) // Optional<Int>
2:13 PM
↑そもそもこれが Optional<Optional<Int>> になると思ってた・・・
Avatar
compnerdさんがコアチーム入りだって windows版公式サポートに進むかな?
すごい。色んなプラットフォームへの展開が Swift 6 の目標に掲げられてて Windows ポート主導してますって紹介されてる compnerd さんがコアチーム入りって、 Swift 6 での Windows サポートあるんじゃないの?
2:13 PM
@omochimetaru try? の flatten って前に proposal なかったっけ?
Avatar
omochimetaru 1/23/2020 2:14 PM
話題2つあるから部屋わけますね
2:15 PM
try? のflatten確かに記憶あるの思い出してきた (edited)
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 1/23/2020 2:21 PM
その上でflattenされる方が優先なのか・・・
Avatar
Swift5って書いてあるから5.0botで試したら怒られたw
5:09 AM
returnなしは5.1から
Avatar
omochimetaru 1/24/2020 5:10 AM
そうですねw
Avatar
return付けて4.2で print(type(of: a), type(of: b), result) を出力してみたら 5.xと同じで悩んでる
Avatar
omochimetaru 1/24/2020 5:15 AM
aとbの値も同じ?
Avatar
sil見たら型推論が変わってる 4.2は () throws -> Int を使ってる
Avatar
omochimetaru 1/24/2020 5:18 AM
お、ですよね
5:18 AM
だから、SE-0230でtry?の仕様が変わりつつも
5:19 AM
いや、だめか、挙動が変わった。
5:19 AM
flattenするからtry?後の式の型は変わってないけど。
Avatar
omochimetaru 1/24/2020 6:59 AM
Swift6でVariadic Generic Parameterをどうやって実装するのか気になって勉強が手につかない
6:59 AM
ツイッターで会話してたんですが、仕様や実装の上で悩ましい点が結構ありますね
7:03 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - technicated/swift-evolution
7:04 AM
このスレッドのAndrea Tomarelliさんのproposal draftでなんとなくできてるけど
Avatar
タプルにしか展開できないように見えますね
Avatar
omochimetaru 1/24/2020 7:04 AM
// ============================================================================= // With the following hack, the result type of the second `curry` function might // become expressible. // ============================================================================= enum CurryHelper<variadic T, Result> { #ifempty T typealias Fn = Result #else typealias Fn = (#head(T)) -> CurryHelper<#tail(T), Result: Result>.Fn #endif } // CurryHelper<A, B, C, R>.Fn // CurryHelper<A, B, C, R>.Fn = (A) -> CurryHelper<B, C, Result: R>.Fn // -> (B) -> CurryHelper<C, Result: R>.Fn // -> (C) -> CurryHelper<Result: R>.Fn // -> R // CurryHelper<A, B, C, R>.Fn = (A) -> (B) -> (C) -> R func curry<A, B, C, variadic D, Result>( _ fn: @escaping (A, B, C, D...) -> Result ) -> CurryHelper<A, B, C, D..., Result>.Fn { return { a in curry { otherValues in fn(a, otherValues...) } } }
Avatar
でもこれをまともに運用するためにはタプルがnominalにならないといけないんじゃ
7:05 AM
お、、、パラメータ側もやるのか
Avatar
omochimetaru 1/24/2020 7:05 AM
↑の#ifempty + typealias はまあ確かに書けてる
7:06 AM
タプルがnominal
↑nominalかどうかは関係ない気がする
Avatar
いや、展開されたタプルを利用する側が
7:06 AM
まともに書けないんじゃぁ意味がない
7:07 AM
それをまともに使えるための構文なり言語機能なりが必要
Avatar
omochimetaru 1/24/2020 7:08 AM
func getFirstMember<variadic T>(_ values: T) -> #head(T) { return #head(values) }
7:08 AM
#head#tail とかは、variadic T自体に型操作としても使えるし、variadic T型の式自体に値操作(と同時に型操作)としても使える必要があると思う。
7:10 AM
#head#tail#ifempty があれば、再帰的に操作できそう
Avatar
ふむ
7:10 AM
テンプレートみを感じる雰囲気がありますね
Avatar
omochimetaru 1/24/2020 7:10 AM
C++はこういうのいろいろできますね
7:11 AM
たださっきの #ifemptyenum の内側で展開するのはなんかいろいろルール違反を感じるので
7:12 AM
分岐が必要ですよね 型レベルの
7:15 AM
enum CurryHelper<variadic T, Result> {} extension CurryHelper where #empty(T) { typealias Fn = Result } extension CurryHelper where #notEmpty(T) { typealias Fn = (#head(T)) -> CurryHelper<#tail(T), Result: Result>.Fn }
7:15 AM
↑こうだったらもうちょっと今のSwift風で許せそう
Avatar
Swiftらしいけどifとnotが別のdeclにあるのがちょっと気持ち悪いですね
Avatar
omochimetaru 1/24/2020 7:18 AM
VD入れた瞬間にコンパイル時計算のドアが開いてしまいそうだなあ (edited)
7:18 AM
ifとnotが別のdeclにある
そうだね〜〜
7:20 AM
enum CurryHelper<vairadic T, Result> { typealias Fn = #condtype(#empty(T), Result, (#head(T)) -> CurryHelper<#tail(T), Result>.Fn) }
7:21 AM
↑こんなのはどうか
Avatar
そうするともうenumでネームスペース切らずに typealias CurryFn<variadic T, Result> = #condtype(#empty(T), Result, (#head(T)) -> CurryFn<#tail(T), Result>) でいい気がしてきました
Avatar
omochimetaru 1/24/2020 7:23 AM
おお。
Avatar
TSっぽくなってきた
Avatar
omochimetaru 1/24/2020 7:26 AM
それスレに書いてきていい?
Avatar
🙆‍♀️
7:27 AM
1年くらい前からスレ立ってるんですね、追ってみよう
Avatar
omochimetaru 1/24/2020 7:27 AM
なんか最初の方は問題を理解してない雰囲気があって
7:27 AM
読めなかった。。
7:51 AM
英語むずい
Avatar
But rule of evaluating #ifempty happens when application of generic parameters is not consistent with existing evaluation of #if.
たしかに〜 #ifemptyは #ifの挙動と紛らわしいですね
(edited)
Avatar
omochimetaru 1/24/2020 7:59 AM
うむ〜
Avatar
可変長引数は (s: S, t: T...) なのに、可変長型パラは <S, T...> じゃなく <S, variadic T> なのはなんでだろう?シンタックス上問題なさそうだけど。
Avatar
omochimetaru 1/24/2020 3:19 PM
スレッドの途中で出てきてるからその辺に会話がありそう
Avatar
omochimetaru 1/25/2020 5:22 AM
Douglas_Gregor struct Variadic<Types...> { init(_ values: Types...) { } } (edited)
5:23 AM
可変長引数(同じ型の配列)と曖昧になるからか。
Avatar
うーん、まあ納得かな。 foo: bar の形式が、 bar の位置に型が来る(宣言時)のと値が来る(呼び出し時)のがあるとか、類似表記で意味が違うとかはあるから許容範囲な気もするけど。まあ、宣言と呼び出しだと、宣言は型なので UpperCamelCase 、呼び出しは値なので lowerCamelCase で一応見分けられるとかはある。 (edited)
Avatar
omochimetaru 1/26/2020 2:37 PM
ん、見分けられなくないですか?
2:39 PM
struct Hoge<T> { func foo(_ values: T...) { } } struct Fuga<T...>{ func foo(_ values: T...) { } } Hoge<Int>().foo(a, b, c, ...) // a, b, c...は全部Intでなければならない、数は自由 Fuga<Int, String, Float>().foo(a, b, c) // a, b, cはInt, STring, Floatでなければならない、数は3つ固定
2:40 PM
HogeとFugaのパラメータ宣言部分まで見ればわかるけど、 同じ記述のfooの宣言だけ見た時の解釈が全くことなる2つの可能性がある (edited)
Avatar
variadic... に置き換えると考えるとして、利用する側には ... はいらないんじゃない? struct Hoge<Ts...> { func foo(_ values: Ts) { } }
2:49 PM
ってか、 variadic ってここに付くの?? struct ZipSequence<S1: Sequence, S2: Sequence, Ss: variadic Sequence> { }
Avatar
omochimetaru 1/26/2020 2:49 PM
あれ、それは変そう
2:49 PM
型パラメータ名の左ですよね
Avatar
制約がない場合は↓なのかな? struct Hoge<Ts: variadic Any> { }
2:50 PM
Proposed Solution にそう書いてあるよ。
2:50 PM
てっきり型パラの左だと思ってた。
2:50 PM
struct ZipSequence<S1: Sequence, S2: Sequence, Ss: variadic Sequence> { private let s1: S1 private let s2: S2 private let ss: Ss // used as a type here, in a property declaration... // ... and here in a function signature init(_ s1: S1, _ s2: S2, _ ss: Ss) { (self.s1, self.s2, self.ss) = (s1, s2, ss) } }
2:51 PM
↑を見る限り、 variadic の利用側には variadic は付かないから、 variadic... でも利用側の ...variadic の意味にならない(可変長引数の意味しか持たない)と思った。 (edited)
2:52 PM
ただ、併用も意味不明な気がするのでコンパイルエラーかな?
Avatar
omochimetaru 1/26/2020 2:52 PM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - technicated/swift-evolution
2:53 PM
1月のどっかのリビジョンで変わってる気がする(これは12月
2:53 PM
func overloaded<variadic T: P1>(ts: T) { } func overloaded<variadic T: P1>(ts: (T...)) { }
Avatar
どういう経緯で変わったんだろう?
Avatar
omochimetaru 1/26/2020 2:53 PM
スレッドの途中で変わったんじゃないですかね?
2:54 PM
まあたしかに、新しいやつだと、プロトコルの前についてますね
Avatar
: の右な理由がぱっと思いつかない
Avatar
omochimetaru 1/26/2020 2:54 PM
なんか
2:54 PM
静的なパラメータ展開じゃなくて
2:54 PM
ランタイム表現の方に気持ちを寄せると
Avatar
func collectionOfValues<T: variadic Any>(_ values: T) -> T { return values }
Avatar
omochimetaru 1/26/2020 2:54 PM
右につくきもちがしてきた
Avatar
おや、本当に : variadic Any なのか。
Avatar
omochimetaru 1/26/2020 2:55 PM
Tっていう文字がたくさん増えるんじゃなくって
Avatar
なるほど
Avatar
omochimetaru 1/26/2020 2:55 PM
Tが、複数型パラメータを意味するパラメータの名前なんだという解釈
2:55 PM
実際ランタイム表現の事は気になっていて
2:56 PM
Swiftの場合はABIPublicじゃなくてもGenericAPIが使える方針だから
Avatar
うん、 Tvariadic なんじゃなくて、 Tvariadic Any を表すんだってことね。
Avatar
omochimetaru 1/26/2020 2:56 PM
コンパイル済みの実体は一つで0〜N個の引数を受け取れる必要がある(ただし一個ずつ型が違う (edited)
Avatar
これも特殊化されたら K 個に展開された版が生成されるのかな?
Avatar
omochimetaru 1/26/2020 2:58 PM
ABIPublicだった場合や事前に指定した場合は0個、1個、2個...の場合は実際に関数が生成されていてほしいですよね。
2:58 PM
その場合は可変長な表現じゃなくて実際にその個数の引数と固定数の型パラメータを持つ。
Avatar
なんかこれすごくマクロっぽくない?
Avatar
omochimetaru 1/26/2020 2:58 PM
てかそうじゃないと、SwiftUIのbuildBlockとかがパフォーマンスリグレッションしちゃうし。
2:58 PM
はい。
2:59 PM
てか、ジェネリクスはだいたい全部、マクロっぽい。
Avatar
Chris Lattner が前に、まだマクロは早いって言ってたけど、将来マクロを導入するのであれば、それも考えて検討した方が良いような気も。
Avatar
omochimetaru 1/26/2020 3:00 PM
うーん?マクロってことは
3:00 PM
どういう記法になりますか?
Avatar
いや、具体的には考えてないけど、
Avatar
omochimetaru 1/26/2020 3:00 PM
可変長ジェネリクスは可変長ジェネリクス用の記法として用意したほうが良いと思います。
Avatar
struct ZipSequence<S1: Sequence, S2: Sequence, Ss: variadic Sequence> { private let s1: S1 private let s2: S2 private let ss: Ss // used as a type here, in a property declaration... // ... and here in a function signature init(_ s1: S1, _ s2: S2, _ ss: Ss) { (self.s1, self.s2, self.ss) = (s1, s2, ss) } }
Avatar
omochimetaru 1/26/2020 3:01 PM
それに制限としてABIPublic限定を強制して、ユーザー側でコード生成させるっていう方針は一つありえると思う。 (edited)
Avatar
↑の Ss とそれを使っている箇所が展開されるのって、これまでの構文と比べて異質すぎて
3:02 PM
たとえば gyb だとそういうことできるけど、それってメタレベルが一個上がってるというか。
3:03 PM
enum CurryHelper<variadic T, Result> { #ifempty T typealias Fn = Result #else typealias Fn = (#head(T)) -> CurryHelper<#tail(T), Result: Result>.Fn #endif }
Avatar
omochimetaru 1/26/2020 3:03 PM
「今まではテキストとしてソースコードを自動生成しないとできなかった事が新たなジェネリクスでできるようになる」事は普通の事ではあると思う
Avatar
このあたりとか。
Avatar
omochimetaru 1/26/2020 3:04 PM
#ifempty や 僕の代案の #condtype はメタレベルというか
3:04 PM
型の表現としてパラメータ展開時に再評価される抽象的な式を導入するので
3:04 PM
まあレベルはあがりますね
3:04 PM
でもそれ故にマクロってのは飛躍があるかなと思います。
3:04 PM
マクロまでいっちゃうと自由度が無制限に吹っ飛んじゃうから。
Avatar
この # による制御が必要になるのは、普通のジェネリクスの導入によってそれまでできないことができるようになったけどこれまでの構文の範囲で吸収できたのとは、ちょっとレベル感が違うと思うんよね。
Avatar
omochimetaru 1/26/2020 3:05 PM
そうですね
3:05 PM
参考までに、typescriptは既にそういう概念を持ってます
Avatar
無制限なマクロじゃなくても、ひとつ上のメタレベルについて、他にやりたいことも考えて整合性を考えなくて良いのかな?という疑問。考えられてるのかもしれないけど。
Avatar
omochimetaru 1/26/2020 3:06 PM
他にやりたいことも考えて整合性を考えなくて良いのかな
なるほど。
Avatar
Variadic Generics だけを見て構文考えてて大丈夫かなと。
Avatar
omochimetaru 1/26/2020 3:06 PM
Variadic Genericと同じぐらい複雑なレベルの機能とか、更にそれを超える機能まで想定して
3:06 PM
一貫性が壊れないようなものを設計してほしいですね。
Avatar
async/awaitthrows/try をメタに考えてなかったら整合性のとれない構文を導入することになってしまったのと同じような過ち( C# とか Kotlin とか)を犯してしまうような。
Avatar
omochimetaru 1/26/2020 3:07 PM
それでいうと
3:07 PM
variadic genericsは、generic manifesto に昔から書かれてる一つのアイデアでしかないので
3:07 PM
generic manifesto全体を考慮できていれば良さそう
3:08 PM
あとこの間のUI of generics
Avatar
しかも # はすでに色々使われてるし、本当にそこのレベルと同じレベルのものなのかな?
Avatar
omochimetaru 1/26/2020 3:08 PM
確かに # のニュアンスは怪しいですね。
3:08 PM
コンパイルタイム時評価って気持ちが # には入ってるように思うけど
3:09 PM
variadic genericsのコンパイル済み関数が実行時に0〜Nで対応できるものなのであれば
3:09 PM
別にコンパイルタイム時じゃないんだよな。
3:09 PM
#first とか #tail とか。 でも #condtype はコンパイル時な気がする。
Avatar
もう少し汎用的なメタ制御構文みたいなので扱わなくて大丈夫かなぁ・・・
Avatar
omochimetaru 1/26/2020 3:11 PM
いや、 #condtype も頑張れば実行時に動的にもなるはずか・・・?
Avatar
あれ? CurryHelpervariadic T のままだw
Avatar
omochimetaru 1/26/2020 3:13 PM
CurryHelperはなくなってますよ
3:13 PM
Andreaさんが昨日proposalを更新していて
3:14 PM
そこでcurryの対応をオミットしたんだって
3:14 PM
スレで言ってます。
3:14 PM
多分Andreaさんの実装では、variadic genericsを、
Avatar
あ、リロードしたら消えたw
Avatar
omochimetaru 1/26/2020 3:14 PM
実行時に、型と値のペアの配列として表現するような仕組みを考えているんじゃないかな
3:14 PM
で、curryだけは
3:15 PM
curry自体の返り値の型が
3:15 PM
その配列的なもので表現できないんですよね
3:15 PM
階数の異なる関数型として返ってくるから。
3:15 PM
そういう意味だと @koher がまさに言っているように
3:16 PM
Andreaさんのアプローチだと、過剰な制約をいれた実装になっちゃってて
3:16 PM
将来的にcurryも対応しようとしたら全然違う実装が更に必要になっちゃうかも?
Avatar
#ifempty 消えてるけど、これとかこれまでの #if との整合性がヤバくないのかな?
Avatar
omochimetaru 1/26/2020 3:21 PM
僕はヤバいと思うので #condtype を提案しました。
Avatar
#ifempty T ... #elseif FOO ... #else ... #endif
3:22 PM
とか崩壊するよね。
Avatar
omochimetaru 1/26/2020 3:22 PM
#ifempty だと
3:23 PM
typealiasだけじゃなくてfuncとかも挟めるから
3:23 PM
意味不明な事になりそう。
Avatar
#ifempty は実行時に処理されうるんじゃないの?
3:24 PM
typealias だからそんなことはないのか?
Avatar
omochimetaru 1/26/2020 3:24 PM
あーコンパイル済みでも動かすならその必要がありますね。
Avatar
よくわからないんだけど、あるモジュールがさっきの CurryHelper みたいな #ifempty を使った public な API を公開していて
3:25 PM
それで動かすには実行時に処理する必要があるけど、
3:25 PM
その実行時の部分に typealias が書かれてるってどうなるの??
Avatar
omochimetaru 1/26/2020 3:25 PM
前提の確認ですけど
3:25 PM
さっきまでマクロって言っていたけど
3:26 PM
マクロではできない ABI non public でも動くことを前提の話ですか? (edited)
Avatar
あー、 ABI public になる前提なのか。
Avatar
omochimetaru 1/26/2020 3:27 PM
いいえ、そこは、僕はproposalからは確認できてないです
3:28 PM
ABI Public 前提で、利用側でのコード生成を前提なら、いろいろ簡単になると思います。 C++のテンプレートと同じように、C++が既にできてるそれらが同じようにできる。
3:28 PM
スレッドも90レスあって、 そのあたりの議論はどうなったか調べられてない。
Avatar
今の @inlineable とかって、 #if とかも保持するようになってるの?
Avatar
omochimetaru 1/26/2020 3:29 PM
どうだっけ、実験してみよう
3:29 PM
実装に入ってるケースですか?
Avatar
うん。
3:30 PM
もし今 ABI-public が #if とかを維持しない仕組みだったら、
3:31 PM
#ifempty とか、たとえ ABI-public 前提でも新しい仕組み導入しないといけないよね?
Avatar
omochimetaru 1/26/2020 3:32 PM
[omochi@omochi-iMacPro sif]$ cat c1.swift @inlinable public func foo() -> Int { #if os(macOS) return 1 #else return 2 #endif } [omochi@omochi-iMacPro sif]$ swiftc -emit-module-interface -enable-library-evolution c1.swift && cat c1.swiftinterface // swift-interface-format-version: 1.0 // swift-compiler-version: Apple Swift version 5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15) // swift-module-flags: -target x86_64-apple-darwin19.2.0 -enable-objc-interop -enable-library-evolution -module-name c1 import Swift @inlinable public func foo() -> Swift.Int { return 1 }
3:32 PM
消えてますね。
3:32 PM
あ〜そうか〜・・・
3:32 PM
だから swiftinterfaceってたくさん生成されるのか。
3:33 PM
一つのライブラリから、 x86.swiftinterface arm64.swiftinferface とかがいっぺんに複数生成されるんですよね。
3:33 PM
ビルド時の変数を全部事前展開するのか。
Avatar
なるほど。
3:33 PM
でも #ifempty は展開できない・・・
3:34 PM
さらに、 #ifempty T ... #elseif FOO ... #else ... #endif だと、 FOOos(...) だったときに、それも保持する必要がありそう。
Avatar
omochimetaru 1/26/2020 3:35 PM
てか #ifempty 自体proposalから消えちゃってますね
Avatar
うん、消えてる。
3:35 PM
実装してて無理ってなったのかな?
3:36 PM
え、てか # 全部消えてる?
3:37 PM
# でページ内検索しても何も出てこない・・・
Avatar
omochimetaru 1/26/2020 3:37 PM
はい。
3:40 PM
struct|class|enum SimpleVariadic<T: variadic P1> { } extension SimpleVariadic { var someTs: T { /* ... */ } func testCollection() -> (T...) { // All your `map`, `filter`, etc are here! let arr1: [String] = someTs.map { "\($0)" } let arr2: [P1] = someTs.filter { $0 is Int } let first: P1? = someTs.first return (someTs...) } }
3:40 PM
こんな感じになってますね。
3:41 PM
#ifempty じゃなくて (variadic型).first みたいな。
Avatar
よくわからないんだけど、 TCollectionSequence じゃないけど、この map とかは何なの??
Avatar
omochimetaru 1/26/2020 3:44 PM
variadic type に対する APIのようですね
// Variadic values are somewhat "special", because both inside and outside of a // generic context act like a Collection - or better are a Collection. The // Element of this collection is the constraint of the Variadic Generic. In- // side a generic context, the ... syntax allows users to convert this collec- // tion to a tuple whose shape and types will be the concrete types passed to // the Variadic Generic parameter.
3:44 PM
だから、 var someTs: T は一見、T型のプロパティに見えるけど
3:44 PM
SimpleVariadic<T: variadic P1> だから
Avatar
えー、無理じゃないかな?
Avatar
omochimetaru 1/26/2020 3:45 PM
someTs: T は、 variadic P1 型としての、型を持つ
3:45 PM
から、map とか first とかでコレクション操作ができる。
Avatar
いや、いいのかな?制約があれば
3:46 PM
↓は可能か。 extension SimpleVariadic { var someTs: T { /* ... */ } func testCollection() -> (T...) { let arr = someTs.map { $0.methodOfP1() } return (arr...) } }
Avatar
omochimetaru 1/26/2020 3:47 PM
methodOfP1() の返り値が Self ならいけるのかな・・・? testCollectionの返り値 (T...) が怪しい木が
Avatar
そこ怪しすぎるよね
3:48 PM
extension SimpleVariadic { var someTs: T { /* ... */ } func testCollection() -> (T...) { let arr = someTs.filter { _ in Bool.random() } return (arr...) } }
3:48 PM
型不定
Avatar
omochimetaru 1/26/2020 3:49 PM
うーんこれおかしいなあ
Avatar
コンパイラ実装できない気がする。
Avatar
omochimetaru 1/26/2020 3:49 PM
あ、いや、一応・・・サンプルコードは
3:50 PM
func testCollection() -> (T...) { // All your `map`, `filter`, etc are here! let arr1: [String] = someTs.map { "\($0)" } let arr2: [P1] = someTs.filter { $0 is Int } let first: P1? = someTs.first return (someTs...) }
3:50 PM
returnしてるのはsomeTs... だから
3:50 PM
tomeTs...(T...) なのは、まあそうかも。
3:50 PM
var someTs: T において (someTs...) の型が (T...) だというのは
3:51 PM
よくわからないけど。
Avatar
え?でも T しか展開できなくて、 map の戻り値が T にならなかったら何もできなくない??
Avatar
omochimetaru 1/26/2020 3:51 PM
T って一つで書いてもコレクション的なもので (T...) って書いたらタプル展開?
Avatar
うん。そうだという認識。
Avatar
omochimetaru 1/26/2020 3:51 PM
はい、arr1 , arr2, first は意味ないですねこの例だと returnしてないんで
3:52 PM
このproposalは詳細が詰めきれてないような気がする
Avatar
関数の中ではコレクションに見えて、外から見ると型の列に見えるような存在ってことなんだと思うんだけど、
3:52 PM
func testCollection() -> (T...) { let arr = someTs.map { $0.methodOfP1() } return (arr...) }
3:52 PM
↑のようなことがしたいんじゃないかと思ってる。
Avatar
omochimetaru 1/26/2020 3:52 PM
こんなふうに書けたらいいよね、ぐらいのになってて、厳密な一つ一つのルールがわからん
3:53 PM
その場合は methodOfP1 の返り値が -> Self だったら
3:53 PM
arr の型も T になって、
3:53 PM
辻褄は合いそう。
Avatar
あ、ちがうか、 map じゃなくて modifyEach か、 (T) -> T に縛られた map じゃないといけないのか。
Avatar
omochimetaru 1/26/2020 3:54 PM
そうです
3:54 PM
let brr = someTs.filter { $0 is Int } ↑これとか、brr の型は [Int] しか無さそうだけど
Avatar
それくらいしか使えないよね。 filter はしたら型不定でダメな気が。 mapArray になるなら OK だね。
Avatar
omochimetaru 1/26/2020 3:54 PM
そんな高階関数filterの型チェック特別に実装するのは現実的じゃ無さそうだ
Avatar
あーでも someTs.map { $0 } の扱いが面倒そうだな。
3:56 PM
[P1] でいいのかな?
3:56 PM
reduce とかは、普通に使えると思うんよね。
3:57 PM
func some<Ts: variadic IntConvertible>(_ values: Ts) -> Int { values.reduce(0) { $0 + $1.asInt() } }
3:57 PM
filter はダメだね。
3:59 PM
for はありなのかな? func some<Ts: variadic IntConvertible>(_ values: Ts) -> Int { var some: Int = 0 for value in values { some += value.asInt() } return some }
Avatar
omochimetaru 1/26/2020 4:00 PM
forはその中で出来ることが自由すぎて
4:00 PM
コンパイル時計算みたいな話になっちゃいますね
4:00 PM
要するに、 [Any] 型の値 array がある時点で実際の値が [Int, String, Float] だったとわかっているときに (edited)
4:01 PM
いろんな操作した結果の型がどうなってるか調べられるようにする、みたいな話に感じる
Avatar
map とか reduce もじゃないの?クロージャに何でも書けるよ。 < 自由すぎ
Avatar
omochimetaru 1/26/2020 4:02 PM
あ〜 そうか、だめそうだなあ
Avatar
for だとしても、 Ts の制約で表される型以外のことはできないし、結果として Ts を得ないならいけるんじゃないかな?
4:03 PM
どっちにしろ、特殊化はできなさそう。
Avatar
omochimetaru 1/26/2020 4:03 PM
var i = 0 someTs.map { i+=1 return i%2 == 0 ? Int(1) : String("") }
4:03 PM
↑こんなこととかもできちゃいますね。
Avatar
map の結果が [Any] ならいいんじゃないの?
4:04 PM
mapTs を得ることは諦めてる。
4:04 PM
Ts のままで有用な操作をするなら modyfyEach 的なものがいるね。
Avatar
omochimetaru 1/26/2020 4:04 PM
それならまあ良さそうですが
4:04 PM
例えば
4:04 PM
self.someTs = someTs.map { $0 + 1 } これとかも通らないか。まあいいか。 (edited)
Avatar
あと、 for inout t in someTs
4:05 PM
うん。究極的には someTs.map { $0 } で、これの戻り値の型を Ts じゃなく [P1] にするならいい。 (edited)
4:07 PM
modifyEachfor inout があれば Ts のまま操作できるし、その場合は要素を P1 として扱えるから色々できるし、あとは集約して別の型に変換するくらいしかできることなさそう。
4:09 PM
んー、ここには ... 展開出てこないの?? struct ZipSequence<S1: Sequence, S2: Sequence, Ss: variadic Sequence> { private let s1: S1 private let s2: S2 private let ss: Ss // used as a type here, in a property declaration... // ... and here in a function signature init(_ s1: S1, _ s2: S2, _ ss: Ss) { (self.s1, self.s2, self.ss) = (s1, s2, ss) } }
4:09 PM
頭からちゃんと読んでないからかもしれないけど、どういう構文なのかよくわからない・・・。正式な Proposal になってから読もう・・・。
4:10 PM
あ、ちがうか
4:10 PM
これは代入してるだけだからいいのか
Avatar
omochimetaru 1/26/2020 4:10 PM
左はパターンだからいいですけど
4:10 PM
右はタプルだから
Avatar
func zip<S1: Sequence, S2: Sequence, Ss: variadic Sequence>( _ s1: S1, _ s2: S2, _ ss: Ss ) -> ZipSequence<S1, S2, Ss> { return ZipSequence(s1, s2, ss) }
Avatar
omochimetaru 1/26/2020 4:10 PM
(S1, S2, Ss) みたいな型になってますね
4:11 PM
Ssの中身は展開されてないあくまで3要素のタプル
4:11 PM
さっきまでの...だとSsが展開されてタプルの要素数がSsのvariadic数に応じる
Avatar
これもまあいいのか。
Avatar
omochimetaru 1/26/2020 4:11 PM
あれ?いいのか?
4:11 PM
ZipSequence(1, 2, 3, 4, 5)
4:11 PM
ってかいたときとズレてるような。
4:12 PM
タプルの規則と合わせるなら ZipSequence(s1, s2, ...ss) になりそう?
Avatar
extension ZipSequence.Iterator: IteratorProtocol { // The result of `next` is a tuple containing an `Element` of `S1`, an // `Element` of `S2` and an element of each member of `Ss` func next() -> (S1.Element, S2.Element, Ss.Element...)? { if reachedEnd { return nil } // We are going to talk about `project` later, in the *detailed design* // section // Moreover, please note that a variadic value of optional elements can be // directly used in pattern matching expressions guard let e1 = baseStream1.next(), let e2 = baseStream2.next(), let es = otherStreams.project({ $0.next() }) else { reachedEnd = true return nil } return (e1, e2, es...) } }
4:12 PM
ここで展開してるからいいのかな。
Avatar
omochimetaru 1/26/2020 4:13 PM
ZipSequence.init だけを見た時の整合性が変な気がする。
Avatar
この project(T) -> Tmap なのかな?
Avatar
omochimetaru 1/26/2020 4:13 PM
// the function is defined something like this mutating func project<T>(_ transform: (inout Self.Element) throws -> T) rethrows -> <variadic value of T's> { return try indices.map { index in try transform(&self[index]) } } (edited)
Avatar
<variadic value of T's> が構文なのか、構文未定なのかどっちなんだろ?
4:15 PM
やっぱ正式な Proposal になってから読まないとあんま意味なさそうな気がしてきた・・・
Avatar
omochimetaru 1/26/2020 4:16 PM
僕もコアチームはこれはあんまり気にせず進める気がします
4:16 PM
ただコミュニティがいろんな意見を言ってそれが集まってるのは良くって Example1,2,3,4,5は
4:17 PM
やりたい事集として良いと思う
Avatar
それにこれを見たおかげで Variadic Generics でどんなことを考慮しないといけないのか少し頭の中を整理できた気がする。
Avatar
omochimetaru 1/26/2020 4:18 PM
たしかに。
Avatar
そうかー。 zip をするためには型の map が必要なのか。
4:23 PM
SS: variadic Sequence から、 next の中で (SS.Element...)> に変換しないといけないのか。
4:24 PM
さっきの (T) -> T 変換と for inout じゃできないな。
Avatar
omochimetaru 1/26/2020 4:25 PM
どういう意味ですか?
4:26 PM
projectが T -> T 変換だから さっきのproposalのコードみたいに project で書ける(?)のでは?
Avatar
Iterator から Element を取り出すから (T) -> T じゃなかった。
Avatar
omochimetaru 1/26/2020 4:28 PM
ああ、 SS から SS.Element への変換か。
Avatar
associatedtype とかメタタイプとかへの型の map みたいなのが必要そう。
Avatar
omochimetaru 1/26/2020 4:28 PM
そゆことか otherStreams.project({ $0.next() }) ↑じゃあこれは
4:29 PM
かなり高度な事をやってますね。
Avatar
うん。
4:30 PM
modifyEach, for inout, reduce, for に加えて型マップくらいがあれば道具は足りるのかなぁ。
4:30 PM
でもそのアプローチ特殊化できないよね。
4:30 PM
SwiftUI のパフォーマンスを考えるとどうすればいいんだろう?
Avatar
omochimetaru 1/26/2020 4:31 PM
あれは TupleView<...> にしたいだけだろうから
4:31 PM
このあたりの話でいくとかなり小さな要件しかなさそう。
4:31 PM
たしか、TupleViewって TupleView<(Text, Image)> みたいに
4:32 PM
型パラメータは1個で、タプル使って擬似的にn個にしてるし。
4:32 PM
func buildBlock<T: variadic View>(views: T) -> TupleView<(T...)> { TupleView((views...)) }
4:32 PM
↑実装側(SwiftUIの中のコード)としてはこれだけじゃないかしら。
Avatar
あー、えっと、 SwiftUI のことを考えるとっていうのは、 SwiftUI で必要とされてる要件を実現するというより、( SwiftUI が必要とするように)モジュールをまたいだ特殊化を前提として、一般的な Variadic Generics を考えるとどういう仕組みだといいんだろうってことを言いたかった。
Avatar
omochimetaru 1/26/2020 4:34 PM
モジュールをまたいだ特殊化
またいだ特殊化?
Avatar
@inlineable のように、別モジュールから使うときにも特殊化されるようにしたいってこと。
Avatar
omochimetaru 1/26/2020 4:37 PM
特殊化するには絶対、ABIPublicな必要があって、
4:37 PM
SwiftUIで必要な範囲だったら、 引数で受けたN個のパラメータパック を、 タプルにする構文(splat) があれば、足りそう。
Avatar
SwiftUI の名前を出したのは SwiftUI にこだわってるわけじゃなくて、単に SwiftUI にすでにそういうものがあって Variadic Generics を使ってもパフォーマンスを保ちたいニーズがあるから挙げただけで、他のどんなケースでも(たとえば標準ライブラリに任意個数の zip を追加するとしても)ベタ書き展開したのと同じパフォーマンスを実現できるような特殊化を実現するために、どういう方法があるんだろう?と。
4:40 PM
ABI-public なのは前提として。
4:41 PM
さっきの map とか for とかみたいなやり方だとうまく特殊化できなさそう。
Avatar
omochimetaru 1/26/2020 4:41 PM
なるほど。Example1...5を再検討するのがベストそう ZipSequence難しいですね。
Avatar
うんむずい
Avatar
omochimetaru 1/26/2020 4:47 PM

追記

@niinaさんから有り難いコメントを頂き、type_traitsを使い一部コードを修正しました。(詳しくは[gitのコミット](https://github.com/pshiko/czipp/commit/f217456...
4:47 PM
C++の実装例を見てみた
4:50 PM
タプルのイテレータとして作って、 next()相当の部分(operator*) は、std::tieとstd::getとstd::make_index_sequenceで作って、 ==はany_cmp_implという関数を作って再帰してた
4:51 PM
std::enable_if_tによるコンパイル時型計算が活用されてますね
Avatar
うーーん、読めない・・・。いずれにせよそういうメタな道具が必要ってことだね。
Avatar
omochimetaru 1/27/2020 1:29 AM
このCPP TMPと、件のproposalはだいぶ次元が違う世界だから、ギャップの理解が難しいけど
1:30 AM
可変長パラメータの取り扱いに関して言えば
1:31 AM
T...での宣言と展開、t...での値の展開しか、
1:31 AM
特別なものはなさそうなんだよな。
1:31 AM
それ以外は汎用的?なTMP(template meta programming)
1:32 AM
の道具でできてる
Avatar
思ったんだけど、求められてるのってタプルに対する演算なんじゃないかな?可変長型パラを型として使うとそれらを展開したタプル型として扱われて、タプルの構造を維持したまま個別要素に対する操作を行える方法を提供する。 タプルの要素に対する制約があるから、制約の範囲で共通の操作を受け付けられる。必要な操作の種類は、map的なものとreduce的なもの。タプルからタプルへの変換と考えれば型の変化も受け入れられる。後は、タプルの中に展開する ... があればやりたいことは大体できそうな気がする。
Avatar
可変長型パラと独立にタプルの各要素を操作する方法が提供されていれば(↓の場合はメソッドの形で提供しているけど別の方法も考えられる)、それを土台にして可変長型パラを論じられないかな? func square<T1: Numeric, T2: Numeric>(of values: (T1, T2)) -> (T1, T2) { values.map { $0 * $0 } } square(of: (3, 5.0)) // (9, 25.0) func firsts<S1: Sequence, S2: Sequence>(of sequences: (S1, S2)) -> (S1.Element?, S2.Element?) { sequences.map { $0.first } } firsts(of: ([2, 3, 5], "XYZ")) // (2, "X") func descriptions<T1: CustomStringConvertible, T2: CustomStringConvertible>(of values: (T1, T2)) -> (String, String) { values.map { $0.description } } descriptions(of: (42, true)) // ("42", "true") func sum<T1: IntConvertible, T2: IntConvertible>(of values: (T1, T2)) -> Int { values.reduce(0) { $0 + $1.asInt() } } sum(of: (3, 5.0)) // 8 (edited)
Avatar
↑のタプルに対する操作を可変長型パラに拡張して func square<T...>(of values: (T...)) -> (T...) { values.map { $0 * $0 } } square(of: (3, 5.0, Complex<Double>.i)) // (9, 25.0, (-1.0, 0.0)) func firsts<(S: Sequence)...>(of sequences: (S...)) -> ((S.Element?)...) { sequences.map { $0.first } } firsts(of: ([2, 3, 5], "XYZ", 42...)) // (2, "X", 42) func descriptions<(T: CustomStringConvertible)...>(of values: (T...)) -> (String...) { values.map { $0.description } } descriptions(of: (42, true, "XYZ")) // ("42", "true", "XYZ") func sum<(T: IntConvertible)...>(of values: (T...)) -> Int { values.reduce(0) { $0 + $1.asInt() } } sum(of: (3, 5.0, "7")) // 15
Avatar
omochimetaru 1/27/2020 7:08 AM
たしかに可変長型パラメータより基本の道具としてタプルの静的な型操作がありそう
7:08 AM
ただやはりmapやreduceの中に書ける計算の質のルールが何かしら必要そう
7:11 AM
文字列固定のやつはいかそう Selfのままと Associatedtypeは対応したいけど
7:11 AM
その2つだけの特別な扱いというより
7:11 AM
なんか規則的な事があるような気がする
Avatar
SelfAssociatedType に限らず、制約から導かれる T -> K として一般化できないかな?
7:24 AM
たまたま KT 自身だったり、 Tassociatectype だったりするだけで。
Avatar
omochimetaru 1/27/2020 7:25 AM
一般化したい
Avatar
omochimetaru 1/27/2020 7:37 AM
あーーなんか閃いてきた
7:38 AM
(移動中・・・
7:43 AM
sequences.map { $0.first }
7:43 AM
↑ここのmapに与えてる関数の型を考えたんですけど
7:43 AM
<T: Collection>(_ x: T) -> T.Element (edited)
7:44 AM
↑型としてはこのように書けると思います。
7:44 AM
で、何が引っかかっていたかと言うと
7:44 AM
今のSwiftでは関数型オブジェクト(クロージャ)は、 ジェネリックパラメータを取れないんです
7:44 AM
だから、まずそこを拡張する必要がある。
7:45 AM
次に
7:46 AM
ある多相な型関数 <A>(A) -> B を考えると
7:47 AM
あいや、 <A>(A) -> <B>B かもしれないんですけど
7:47 AM
この計算(AからBを求めること)を記述できる言語機能は
7:47 AM
多分 struct に対するメンバの typealias しかない。
7:47 AM
で、ただ、 <A>A が多相なので
7:48 AM
<A> に与えられる実際の型を規定するのが、
7:48 AM
言語機能としての protocol だと思う。
7:49 AM
つまり、 <A>(A) -> <B>Bprotocol AP { associatedtype R } なときに、 <A: AP>(A) -> R な式が持ってる型。
7:51 AM
普通のクロージャ構文だと、 $0 って書いた時点でもうなんらかの T としてのコンパイルになっちゃってクロージャも (T) -> U になるけど、 そうじゃなくて <A: P>(A) -> U のほうにならないといけない。
7:51 AM
でそれがあると、
7:52 AM
動的なタプルの場合は動的な処理としてさっきのmapが動かせて
7:52 AM
もし入力元のタプルの型が静的にわかっているときは、
7:53 AM
静的解析で結果のタプルの型がわかる。
7:54 AM
$0.first は、 $0 の型がわかっている(<A>(A) -> BA が特定できる)ときには、 .first の型が静的にわかるけどそれは、 .firstassociatedtype を与えているprotocolがあって、それを個別の A が充足してる typealias が静的に見えるから、です。
7:56 AM
任意の x.y の形の式に対して、 x の型があるプロトコルで制約されていて、 y がそのプロトコルのメンバなのであれば、 x.y は静的に具体的な型が決定できる式、って事になりそう。
7:56 AM
x だけのときは <A>(A) -> A まあつまり <Self>(Self) -> Selfとして同じことが言える。
7:58 AM
式が複雑になって?そうじゃないものが式の中に混ざり込んだ時は、静的に決定できない式になって、 タプルのmapとしては、全部の要素の型が同じタプルになっちゃう。
7:58 AM
そうじゃないものって存在しない気がするな?
8:00 AM
必ず何らかの式の型はあるから型は決定できるけど、 <A>(A) -> BB が <A> を充足する個別の T に対して静的に解決できる型の場合と <A> に入る T がなんであろうが固定の型になっちゃう場合 ( description($0) など )がある。
8:01 AM
この、個別に異なりえて、かつそれが静的に決定できる場合と、 そうでなくて固定になっちゃう場合が、またなんかちゃんと述べられる気がする。
8:01 AM
やっぱ <A>(A) -> <B>B<A>(A) -> B の違いなんじゃないか??
8:03 AM
なぜなら、 map に <A>(A) -> B を与えたらそりゃ結果は (B, B, B, ...) でしか無いはずなので。
8:04 AM
で、結果の型は、呼び出し側から決定できるわけじゃないから、リバースジェネリックパラメータがあるってことになりそう。
Avatar
(String...) については、本当は (type(of: T.description)...) なんよね。 associatedtype との違いは、それを記述するシンタックスがないだけで、どちらも T によって一意に決まる点は同じ。
8:13 AM
CustomStringConvertible に準拠した型の description という時点で String が決定される。
8:14 AM
associatedtype の場合は個々の T によって別の型が導かれる。
8:14 AM
シンタックスの問題以外は同じ話だと思うけどなぁ。
Avatar
omochimetaru 1/27/2020 8:14 AM
いや、そこが違うと思います
8:15 AM
CustomStringConvertibledescription
8:15 AM
<T: CustomStringConvertible>T がたとえわかっていなくても String であるとわかるけど
8:15 AM
associatedtype の場合は個々の T がわかってないと 導く型がわからない。
8:16 AM
そこには型システム的な意味の違いがある気がする。
Avatar
それはそうだけど、それって↓の差と同定の話だと思うけど。 ```swift func first<S: Sequence>(of sequence: S) -> S.Element? { sequence.first } ``` ```swift func description<T: CustomStringConvertible>(of value: T) -> String { value.description } ```
Avatar
omochimetaru 1/27/2020 8:18 AM
あ〜そうか。 S.Element な時点で パラメータ的な型になっているのか。
8:20 AM
ただ、クロージャとして入力パラメータが残ってないといけないという違いはやっぱりあると思います。
8:20 AM
descriptionの例は (CustomStringConvertible) -> String 型のクロージャを渡してるって事でも説明ができるけど
8:21 AM
firstの例はexistentialで考えると書けない
Avatar
入力パラメータが残ってないといけない
これはそうだと思うけど、それって associatedtype に限らず、可変長型パラを使う時点で残しておこないといけないよね?
Avatar
omochimetaru 1/27/2020 8:22 AM
はい、可変長型パラに対するコレクション操作みたいなことをやろうとしたら
8:22 AM
その操作を記述するクロージャは型パラメータを取るんじゃないかって事です。
Avatar
CustomStringConvertible の方のクロージャも、 existential ではなくて、あくまで型パラを埋められたときに決定される T を使って (T) -> String となるイメージ。
8:23 AM
タプルの操作と可変長型パラを同時に考えるとややこしいから、まずは普通のタプルについて考えたら
Avatar
omochimetaru 1/27/2020 8:23 AM
動的な振る舞いを考えるとそういう事だと思います。
Avatar
func firsts<S1: Sequence, S2: Sequence>(of sequences: (S1, S2)) -> (S1.Element?, S2.Element?) { sequences.map { $0.first } }func firsts<S1: Sequence, S2: Sequence>(of sequences: (S1, S2)) -> (S1.Element?, S2.Element?) { (sequences.0.first, sequences.1.first) } のシュガーみたいに解釈できると思うんよね。
8:25 AM
シュガーとして考えるときにメソッドという形がややこしければ、別の新しいシンタックスを導入してもいい。
Avatar
omochimetaru 1/27/2020 8:26 AM
// Array func map<T, U>(_ f: (T) -> U) -> Array<U> // Tuple3 func map(_ f: <T, U>(T) -> U) -> (<type(of: f(E1)), type(of: f(E2)), type(of: f(E3)) )
8:26 AM
↑こういうことじゃないかしら??
Avatar
もう少し正確に書くと↓かな。 func firsts<S1: Sequence, S2: Sequence>(of sequences: (S1, S2)) -> (S1.Element?, S2.Element?) { ({ $0.first }(sequences.0), { $0.first }(sequences.1)) }
Avatar
omochimetaru 1/27/2020 8:27 AM
シュガーみたいに解釈できる
期待してる実行結果がそうなのはそうですが、 それをジェネリックに表現する型の言葉が必要だと思います。
8:27 AM
それは、これまでのジェネリクスでも同じ事で
Avatar
えっと、普通のタプルについては完全にシュガーとして変換できるよね?
Avatar
omochimetaru 1/27/2020 8:29 AM
struct Box<T> { var x: T } // に対して // Box<Int> は struct Box<Int> { var x: Int } // というシュガー展開として解釈できる // 実際最適化でもそうなる、 // でも動的な動作の場合は、↑と同じ結果をもたらす一つの仕組みになる
8:29 AM
クロージャの中身が見えないので変換できないです。
Avatar
解釈だけじゃなくて、普通のタプルに対する map はコンパイル時に展開できる。
Avatar
omochimetaru 1/27/2020 8:29 AM
mapがinlinableならできるけど。
Avatar
可変長を混ぜて考えるとややこしいから、まずは普通のタプルについて考える。
8:30 AM
その後、可変長型パラとの組み合わせにおける拡張を考える。
8:30 AM
↑の 2 要素固定タプルでコンパイラが書き換えできない例ってあるかな?
8:31 AM
@escaping とか
Avatar
omochimetaru 1/27/2020 8:31 AM
2要素タプルは言語に1個しかないから
8:31 AM
仕様が固定されれば、ユーザー側で展開できると思います
8:31 AM
それは普通のgenericsでも同じ事で。
Avatar
色々工夫が必要なケースがある気がしないでもないけど、基本的にできると思うんよね。
8:32 AM
いや、利用側じゃなくて、その関数で完結して展開できるよね?
Avatar
omochimetaru 1/27/2020 8:32 AM
なんだろう、ABIPublicでコード展開が可能っていう方針で考える限り
Avatar
ABI-public である必要すらない。
Avatar
omochimetaru 1/27/2020 8:32 AM
型とか考えなくて良い気がするんですよね
8:32 AM
展開後のコードについて型チェックすれば良いから。
8:33 AM
gybを使ってるときと同じノリ。
8:37 AM
tuple.map { expression } って形で書ける事にすることで、 見かけはSwiftコードっぽくなるけど、 このmapをコードの展開として考えるのであれば、 あくまで型システムや実行モデルで考える必要があるのは、 展開後のコードだけの話になるので、 なんだろう、見た目がおしゃれなgybみたいな感じの話になると思うんです。
8:38 AM
その方針で突き詰めていっても最終的に、 ユーザー定義可変長ジェネリクスの話まで到達した時に、 実行モデルの話が出てきて止まっちゃうので、 最初から、 tuple.map { expression } ↑コレ自体をSwiftのコードとして受け付けられるようにする方法を考えたほうが良い気がします。
Avatar
うん、可変長型パラを考えたらそこで実行モデルの話が出るのはその通りだけど、
8:42 AM
それって(普通の)型パラが特殊化されなかった場合に三組で扱うのと同じような話で、それを扱えるモデルを導入すれば済む話なんじゃない?
8:43 AM
特殊化されれば可変長でも展開されるし、特殊化されなければその実行モデルで動的に処理される。
8:43 AM
あと、可変長型パラまでの間にもう一つ可変長タプルがある気がする。
8:44 AM
func square(of values: (Int...)) -> (Int...) { values.map { $0 * $0 } }
8:44 AM
↑を扱う実行モデルがあれば、それを使って可変長型パラでもいけるんじゃないかな?
8:45 AM
func descriptions(of values: (Int...)) -> (String...) { values.map { $0.description } }
Avatar
omochimetaru 1/27/2020 8:46 AM
それを扱えるモデルを導入すれば済む
実行はそうですね、3つ組ですね で、実行できる前の型チェックが鬼門かなと思います
Avatar
func firsts<T>(of arrays: [T]...) -> ((T?)...) { arrays.map { $0.first } } (edited)
8:47 AM
そうかな?各 T には同じ制約付いてるから、普通にその制約についてチェックするだけじゃない?
Avatar
omochimetaru 1/27/2020 8:49 AM
例えば let aa: [Int] = [1, 2, 3] let sa: [String] = ["a", "b", "c"] let zipped = zip(aa, sa) let fst = zipped.first! let ri : Int = fst.0 let rs : String = fst.1
8:49 AM
↑こう書いた時に、 ri: Intrs: String の部分の型チェックが必要で
8:50 AM
fst の型が (Int, String) であることが、 ZippedSequence.first の型定義シグネチャから導かれないといけない。
Avatar
use-site については型が決まるから展開してから考えるんじゃない?
8:51 AM
問題は declaration-site でどのように扱うかというモデルであって、
8:51 AM
use-site は常に展開したらいいんじゃないかな?
Avatar
omochimetaru 1/27/2020 8:54 AM
展開するために
8:55 AM
ZippedSequence.first の宣言は・・・
8:55 AM
まあなんか書けるか。 Elementのところが可変長タプルになってればよいか。
8:56 AM
気になってるのは2要素タプルのmapで
8:57 AM
extension <A, B> (A, B) { func map(_ f: <T, U>(T) -> U) -> (T, U) } 多分こう
8:57 AM
func firsts<T>(of arrays: [T]) -> ((T?)...) { arrays.map { $0.first } } ↑コレはヤバそうですね、要素数がArrayの動的な個数からタプルの静的な個数にする?
Avatar
ああ、間違えた
Avatar
omochimetaru 1/27/2020 8:58 AM
これは可変長型パラを超えたその先の機能だと思います Arrayの要素数の静的な追跡が必要になる
Avatar
func firsts<T>(of arrays: ([T]...)) -> ((T?)...) { arrays.map { $0.first } }
Avatar
omochimetaru 1/27/2020 8:59 AM
あれ、それだと、Tが同じにみえる
8:59 AM
あ、要素数だけが可変長って事ですか?
Avatar
うん。
9:00 AM
元の方も修正しました。
Avatar
omochimetaru 1/27/2020 9:01 AM
あ〜そうか
9:01 AM
それはそれで必要ですね
Avatar
↓の 3 ステップで実現するのが良いと思う。 1. タプルに対する map-like, reduce-like オペレーション 2. 可変長タプル 3. Variadic Generics
Avatar
omochimetaru 1/27/2020 9:01 AM
gybだとできるけどSwiftでできなくて でも可変長型パラではない。
Avatar
うん。
9:02 AM
1 と 2 の道具があれば、可変長型パラをその上に乗せられると思うんよね。
Avatar
omochimetaru 1/27/2020 9:03 AM
関係はそうなってる気がする。
Avatar
この 3 step はどう?って forum に書いてみようか・・・。
9:03 AM
何か知見が得られるかも。
Avatar
omochimetaru 1/27/2020 9:51 AM
// これは展開できるから良いとして func f1(_ tpl: ([Int], [String])) { let fst: (Int?, String?) = tpl.map { $0.first } } // これもジェネリック型のまま展開できる func f2<T, U>(_ tpl: ([T], [U])) { let fst: (T?, U?) = tpl.map { $0.first } } // でもその変換が外部から来たら展開できない、こうか? func f3(_ tpl: ([Int], [String]), _ g: <A>(A) -> <B> B) { // #decltypeはC++からアイデアを借用 let fst: (#decltype(g(tpl.0)), #decltype(g(tpl.1)) = tpl.map(g) } // これもこう? func f4<T, U>(_ tpl: ([T], [U]), _ g: <A>(A) -> <B> B) { let fst: (#decltype(g(tpl.0), #decltype(g(tpl.1)) = tpl.map(g) } (edited)
9:53 AM
↑やっぱりmapに渡すクロージャの型は、リバースジェネリクスが含まれませんかね? <B> が前にあるとしたら、呼び出し側が決定するわけだけど、 実際g の実装が $0.first なのか description($0) なのかわからないという立場だから、 f3f4 からすると、 <B> のパラメータは指定できない。 (edited)
Avatar
f3 を実現するには↓になるんじゃないかな? func f3<T..., U...>(_ tpl: ([T]...), _ g: ((T) -> U)...) { let fst: (U...) = tpl.map(g) }
10:05 AM
T...U... の数が同じであることや、どの ... がどの ... と対応するのかは、何らかのシンタックスで指定できる必要があるけど。
Avatar
今は、(f1,2,3,4)シンプルに2要素タプルを考えてます (edited)
10:05 AM
可変長パラメータではない。
Avatar
2 要素タプルではできないよ。
10:06 AM
タプルの map は単純にタプルについての式だから。
Avatar
できないとは?f1,f2,f3,f4のどれが変ですか?
10:06 AM
f3 を書くなら↓になる
Avatar
f3では、f1とf2で { $0.first } になっている部分が、引数として外からやってくる場合を考えてます。
Avatar
func f3(_ tpl: ([Int], [String]), _ g: ((Int) -> Foo, (String) -> Bar) { ... }
10:08 AM
タプルの map と関数のシグネチャはまったく関係ない。
10:08 AM
タプルの map はそれを使う式に閉じた話。
10:09 AM
f3 は 2 要素タプルを受け取ってて、それと map には何の関係もない。
10:09 AM
それぞれの要素にオペレーションを指定したいなら、オペレーションも二つ渡さないといけない。
10:09 AM
それを一つにまとめることをしたいなら、さっき書いた↓になる。 func f3<T..., U...>(_ tpl: ([T]...), _ g: ((T) -> U)...) { let fst: (U...) = tpl.map(g) }
10:10 AM
ああ、これでもおかしいか。
10:10 AM
一つにまとめられてるわけじゃないな。
10:11 AM
うーん、そうか。
Avatar
えっと、 2要素タプル (T, U).map(g) という式において、g の型がどういうものかを考えているんですけど、 { $0.first } が渡せるのであれば、これはオペレーション?というか、関数型の値としては、1つですよね?
10:11 AM
でも map から見たら、 渡された g を 2回使うわけです。
Avatar
実行モデルはあくまで内部的なものだから
10:13 AM
それに対応したことができないといけないわけではないんじゃない?
10:14 AM
特殊化されないときの三組を明示的に作れないのと同じように。
10:14 AM
(それができるなら generalized existential みたいなこともできるはず)
Avatar
f1、f2とf3, f4は抽象度が違うので、f3, f4はできるようにはならない、 という仕様で考えること自体は別に良いと思うんですが、 もしできるようになったら型システムにおいてどういう意味を持つかを考えておかないと、 f1、f2の実装が筋の悪いものになっちゃうかもしれない。
Avatar
f3 みたいなのは、 Variadic Tuple だけじゃなくて Variadic Generics の文脈でも意味を持たないと思うんだよなぁ。それを考えるなら、この問題とは独立してまずジェネリック関数オブジェクトを考えないといけないんじゃないかな?
10:24 AM
で、それがあればそれを受け取ることでタプルの map に渡すとかも考えられるようになると思う。それが必要かは別として。
Avatar
f1、f2の時点で、 map にクロージャを渡すところで、 このmap自体のシグネチャがあるはずなので、 (edited)
10:26 AM
f1, f2 でもそこは考えてるはずじゃないですか?
10:27 AM
例えばXcodeで、f1のコードのmapのところをCmd + Clickしたら、mapのシグネチャが出るはず。
Avatar
いや、これはただのクロージャじゃないから、クロージャとメソッドのような構文を採用してるだけで。
10:28 AM
別に↓でもいい。 func squares<T1: Numeric, T2: Numeric>(of values: (T1, T2)) -> (T1, T2) { #map element in values { element * element } }
10:29 AM
実行モデルとしては、ジェネリック関数オブジェクトのようなものを持たないといけないし、
10:29 AM
特殊化されると個別に展開される。
Avatar
実行モデルとしては、ジェネリック関数オブジェクトのようなものを持たないといけないし、
実行モデルとしても、型システムとしてもそれが必要なのではないかなと。 そうでないと、f1のlet fst の型チェックのところで、型推論器が困っちゃうし。 静的なコード展開だけを考えてるなら、いらないとおもいます、 その場合は実行モデルを考える必要も無い その場合は、ユーザーにとってどんな文法で機能を提供すればよいか?を話したいってことですかね
(edited)
Avatar
いや、固定長タプルに対しての mapreduce は静的に展開されるけど、
10:35 AM
可変長タプルや可変長型パラは特殊化されない限り動的に扱わないといけないから
10:35 AM
そこでこれまでにない実行モデルが必要になる。
10:36 AM
そのときにクロージャはジェネリック関数オブジェクトのようなもので扱われると思う。
10:36 AM
コーディングする側は、そこに書くクロージャ式は外で定義された T: Protocol について書くときと同じようになる。
10:38 AM
func square<T: Numeric>(of values: [T]) -> [T] { values.map { $0 * $0 } }
10:39 AM
↑と↓は func square<variadic T: Numeric>(of values: (T...)) -> (T...) { values.map { $0 * $0 } }
10:39 AM
クロージャを書くときの意識はまったく同じだと思うけど。
10:40 AM
それがどのように扱われるかが違うだけで。
10:40 AM
クロージャの中で守るべき制約も、コンパイルエラーになる条件も、何も変わらなくない?
10:41 AM
ABI 上は新しいものを追加しないといけないし、実行時にはジェネリック関数オブジェクト的なものにしないといけないし、特殊化されたら展開されないといけない。
10:41 AM
一度落ちます。
Avatar
それは、例示してるmapの中身が単純だから、性質の違いを踏んでいないだけだと思います。 例えば func square<T: Numeric>(of values: [T]) -> [T] { var sum: T = T.zero let ret = values.map { (a) in sum += a return a * a } print("sum is \(sum)") return ret } // ↑これはコンパイルが通るけど // ↓これはエラーになるはずです func square<variadic T: Numeric>(of values: (T...)) -> (T...) { var sum: T = T.zero // ←まずこれが書けないし let ret = values.map { (a) in sum += a // values.0 と values.1は型が違うから + はできない return a * a } print("sum is \(sum)") return ret }
10:50 AM
ジェネリック関数のジェネリックパラメータは呼び出しのたびに具体型が渡されてくるけど、 前者のArrayの例ではmapのクロージャのa はずっと同じ T 型 (squareのスコープで束縛) だけど 後者のTupleの例ではクロージャの a は呼び出されるたびに別のもの。
Avatar
T はクロージャの中でしか具体的な型を持たないから、クロージャの外で T.zero はできないね。 T はクロージャの外ではそのままでは使えない。 (T...) とか、 (T.Foo...) とか、展開した形でないと。
12:39 PM
そういう意味で確かに array 版とは異なるけど、そういうことじゃなくて、
Avatar
書けるようにするなら var sum: #first(T) とかでしょうね。 (edited)
Avatar
それもだめじゃない?
Avatar
var sum: #decltype(values.0) でもいいか。
12:39 PM
ああ、いずれにせよ、足せないです。
12:40 PM
T はクロージャの中でしか具体的な型を持たない
言いたかったのはそういうことで、型システム的に異なる意味をもっているということです。
Avatar
そこの型にはアクセスできなくていいと思う。
12:41 PM
してたのはクロージャをどう扱うかという話だから、クロージャの中の世界は同じように型検査ができると思うよ。
12:41 PM
外の世界では展開しない T は使えない。
12:41 PM
そのルールでうまくいくんじゃないかな?
12:42 PM
sumやるなら制約を加えて変換できるようにしないといけなくて、IntConvertibleの例みたいに。
Avatar
mapについてはそういうシバリでの実装はできそうですね (edited)
Avatar
reduceも同じ。
Avatar
んーたとえば
12:42 PM
(Int, String, Float)(String, Float, Int) みたいに
12:42 PM
ローテーションするようなオペレーションを作ろうとしたら
Avatar
それはそのためのオペレーション用のメソッドが必要だろうね。
Avatar
また map, reduce とは別の機能が必要そう。
Avatar
このmapやreduceはメソッドじゃなくて特殊構文だから
12:44 PM
足りないものは言語が用意するしかないんじゃないかな?
Avatar
mapやreduceをユーザー実装できるような
Avatar
そこをユーザー定義できるようにするというのは、
Avatar
もっとプリミティブな道具だけ提供する方法があったらよさそう
Avatar
言語のメタレベルを上げないときついと思うよ。
12:45 PM
それこそ、言語の仕組みの上で Variadic Generics を可能にする仕組みを自作できるようなメタ度になるんじゃない?
12:46 PM
制御構文だって自作できないし。
12:46 PM
ちなみに reduce は for でもいいんだけど、
12:46 PM
ループの中だけ T が展開される
12:47 PM
ループ回るたびに別の型として実行される
12:47 PM
でも特殊化が難しそう、と思ったけどループばらすだけだから簡単か。
Avatar
C++のTMPだと変数が絡んじゃうループは使わなくてだいたい再帰とコンパイル定数と分岐でやるけど、 うーんたしかにそういう方針だと必要なものが一気に増えるな
Avatar
ためしに書いてみた。どうでしょ? https://gist.github.com/koher/62ec1cb06258e1d6f034645506e7f99e (edited)
GitHub Gist: instantly share code, notes, and snippets.
5:02 AM
こんな内容で forum に投稿してみたらどうかと考えてるんだけど。
Avatar
omochimetaru 1/28/2020 5:03 AM
長! レスじゃなくて、スレ立て?
5:03 AM
あ、[PITCH]って書いてあった。
Avatar
omochimetaru 1/28/2020 5:12 AM
_ = xs.map { x: T in // ✅ OK
(x: T) じゃないと文法エラー で、それを直したとしても、ここに T はおかしいような。 T じゃないから。
5:12 AM
実際には T1 T2 T3 , ... のように別々の型になってて、毎回違うやつになってるから。
5:13 AM
ソレ以外の全体としては言いたいことが整っててわかりやすいと思いました。
Avatar
ありがとう。 () たしかに。 T は、 variadic generics では T でいいと思うけど、 nomal tuple のときは書きようがないんよね。
6:20 AM
<(T: Protocol)...> で、 T は可変長型パラの一つの型を表すプレースホルダー。
Avatar
omochimetaru 1/28/2020 6:25 AM
variadic generics では T でいい
variadic tupleでは ですか?
6:28 AM
tupleの時はそうですね。 ジェネリッククロージャがもしあれば↓こうかなと思いますけど。 func squares<T1: Numeric, T2: Numeric>(of values: (T1, T2)) -> (T1, T2) { values.map { <X> (a: X) in x * x } }
Avatar
variadic tuple だと要素の型が固定されてるので具体的な型で書けるよ。
7:19 AM
あー、 (Int, Double...) とかもあるから一般的には言えないか。
7:21 AM
variadic generics では T でいい
その言葉の通りです。 func squares<(T: Numeric)...>(of values: (T...)) -> (T...) { values.map { (value: T) in value * value } }
7:22 AM
この T はタプルオペレーションの外では T... としてしか使えないけど、中では T として使えて、 T... の個別の型を表すプレースホルダーとして働く。
Avatar
omochimetaru 1/28/2020 7:39 AM
あ〜、mapの中ではその時のT を表すという解釈か。
Avatar
うん。
7:57 AM
normal tuple のときに制約が適用されるルールが曖昧かなぁ。
7:58 AM
各要素の共通の制約が自動的に適用されるのはあまり swifty でない感じがする・・・。
Avatar
omochimetaru 1/28/2020 7:58 AM
共通のプロトコルを導き出す挙動ってあったかなぁ。
Avatar
これまでタプルの要素に対して共通のオペレーションを行うこと自体ができなかったから、タプルの各要素に共通の制約を適用する構文もなくて、それが問題なんだよなぁ。
Avatar
共通の制約が自動でつくの、goにそういうのありませんでしたっけ
Avatar
stractural subtyping ?
Avatar
そうそう
Avatar
swifty な感じがしないんですよねぇ。
Avatar
omochimetaru 1/28/2020 8:01 AM
Goのstatic duck typingは宣言を伴わないからまた違うと思う
Avatar
この先にgo相当のそれが欲しいという議論が出てきそうだな、と。
Avatar
これは T1T2 がそれぞれ Numeric に適合してることは述べられているけど、 values のすべての要素が共通して Numeric に適合していることは暗黙的だから、 map したときに * できるのは structural subtyping 的だと思う。 func squares<T1: Numeric, T2: Numeric>(of values: (T1, T2)) -> (T1, T2) { values.map { $0 * $0 } }
Avatar
omochimetaru 1/28/2020 8:03 AM
Swift的にはジェネリッククロージャとして自前で宣言する方向だと思います func squares<T1: Numeric, T2: Numeric>(of values: (T1, T2)) -> (T1, T2) { // T1とT2がXに束縛できるか静的にチェック values.map { <X: Numeric> (a: X) in x * x } }
8:04 AM
$0 記法の時は悩ましいな。
8:04 AM
これまで関数のシグネチャが推論されるのはクロージャーだけで、func のシグネチャ推論は存在しなかったから
8:05 AM
クロージャーに存在しないジェネリックパラメータが増えると 推論をジェネリックパラメータで受けるのか型で受けるのか曖昧性が出てくる場所もありそうだ
Avatar
タプルの型宣言に制約を記述できないかな?
8:05 AM
これまで使い道がなかったから構文がないだけで。
8:07 AM
let a: <*: Numeric>(Int, Double) = (2, 3) let b = a.map { (a: X) in a * a } // X: Numberic (edited)
8:08 AM
冗長な感じがするなぁ。
Avatar
omochimetaru 1/28/2020 8:08 AM
func squares<T1: Numeric, T2: Numeric>(of values: (T1, T2) where Element: Numeric) -> (T1, T2) (edited)
Avatar
書かなくても自明なわけだし、自動的に推論されてもいいような気もしてきた。
Avatar
omochimetaru 1/28/2020 8:10 AM
least common conformanceって簡単に求められるのかなあ。 (edited)
8:11 AM
least common supertypeの推論ロジックはあるんですけどね。
Avatar
配列を宣言する時に
8:11 AM
[dog,cat]ってやったらどうなるんだっけ
Avatar
omochimetaru 1/28/2020 8:11 AM
least common supertype
8:12 AM
ただ、Existentialにはならなかった気がする?
Avatar
そう、それと同じ気がしてて
8:12 AM
@swift-5.1.5 func f<X>(_ xs: [X]) { print("Any: \(xs)") } func f<X: Numeric>(_ xs: [X]) { print("Numeric: \(xs)") } f([2, 3, 5])
Avatar
Numeric: [2, 3, 5]
Avatar
omochimetaru 1/28/2020 8:13 AM
それはfのオーバーロード探索だから、求めたい共通性の候補をユーザーが与えている
8:13 AM
@swiftbot class Animal {} class Cat: Animal {} class Dog: Animal {} let a = [Cat(), Dog()] print(type(of: a))
Avatar
swiftbot BOT 1/28/2020 8:13 AM
Author icon
omochimetaru
class Animal {} class Cat: Animal {} class Dog: Animal {} let a = [Cat(), Dog()] print(type(of: a))
Version:
swift-5.1.3-RELEASE
Output:
Array<Animal>
Error:
Avatar
omochimetaru 1/28/2020 8:13 AM
@swiftbot protocol Animal {} class Cat: Animal {} class Dog: Animal {} let a = [Cat(), Dog()] print(type(of: a))
Avatar
swiftbot BOT 1/28/2020 8:13 AM
Author icon
omochimetaru
protocol Animal {} class Cat: Animal {} class Dog: Animal {} let a = [Cat(), Dog()] print(type(of: a))
Version:
swift-5.1.3-RELEASE
Output:
Error:
/usercode/main.swift:5:9: error: heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional let a = [Cat(), Dog()] ^~~~~~~~~~~~~~ as [Any]
Avatar
omochimetaru 1/28/2020 8:14 AM
今はExistentialは無理みたいですね。
Avatar
square のは existential ではないんよね。
Avatar
omochimetaru 1/28/2020 8:14 AM
(今の2つのコードはclass Animalかprotocol Animalを変えてる)
8:14 AM
はい、制約それ自体を推論させる仕組みは多分存在しない
8:14 AM
推論できるのは型パラメータに適用する型の方で
8:15 AM
型パラメータの制約は型ではない
8:15 AM
まあ
8:15 AM
そもそも今できない事を拡張してできるようにする話をしているんで
Avatar
そのものがなくても、類似の仕組みはあるわけだし、制約が推論されても良さそうな気はするね。
Avatar
omochimetaru 1/28/2020 8:15 AM
$0 is Numeric を自動的に推論するんだ」って提案するのは自由ですね (edited)
8:17 AM
ある型が満たすプロトコルを全部列挙することはできるはず(superprotocolを走査)だから 積集合を取るだけな気はしますね
8:17 AM
その後冗長なものを排除した上で残ったもののintersection protocolですね
Avatar
[Pitch] と [Pre-pitch] と [Idea] ってスレッドがあるんだけど、どれがいいんだろう・・・。
Avatar
[Pitch] よりももっとふんわりした話な気がするんだけど、温度感がよくわからない・・・
Avatar
omochimetaru 1/28/2020 8:51 AM
↑一応こういう風に、タグの説明がそれぞれありますよ。
8:51 AM
タグとしては Pitch か Discussion がありますね
8:51 AM
PrePitchはフォーラムのタグじゃなくて勝手にタイトルにつけてるだけ
8:52 AM
The Pitches category is an area for pitching ideas for evolution of the Swift language prior to a formal review. The Evolution Discussion category is for general discussion of the evolution of the Swift language.
(edited)
Avatar
うん、でもニュアンスはわかるんよね。 Pitch の前段階って言いたい。
8:52 AM
Pitches タグを付けた上で [Pre-pitch] とかにしとけばいいかな。
Avatar
omochimetaru 1/28/2020 8:53 AM
Discussionタグは特定のアイデアについて話すやつではなかったのか。今知った。
8:53 AM
そうですね
Avatar
[Idea] の温度感がわからないけど・・・。 [Idea] っちゃ [Idea] な気もするけど。まあ、定義も存在しない雰囲気なんだろうけど。
Avatar
omochimetaru 1/28/2020 8:55 AM
僕が見てる限りはそんなに統一感は無いですよ
Avatar
よくわからんし [Pitch] でもいい気もしてきた
Avatar
omochimetaru 1/28/2020 8:55 AM
初めて投稿する人とか結構定期的に現れるのもあって。
8:56 AM
こういうときは XXタグのほうがいい みたいな指摘自体も見かけない
Avatar
Variadic generics was referred to in "On the road to Swift 6". I think it may be a good idea to break down it into the following three steps compared to tackle variadic generics directly. Operations for tuples Variadic tuples Variadic generics 1. Operations for tuples The ...
Avatar
読みました。3ステップの構成が非常に読みやすかったです!
10:03 AM
func tupleFrom<T>(head: T, tail: (T...)) -> (T, T...) { (head, tail...) } let a: Int = 2 let b: Int = (3, 5) let c: (Int, Int, Int) = tupleFrom(head: a, tail: b) // (2, 3, 5) ここの b の型は (Int, Int) ですかね?
Avatar
返信しづらいリプが付いたなあ
Avatar
Kishikawa Katsumi 1/28/2020 10:51 AM
まあここの議論は見えてないですからね。無視してるんじゃなくてそこからスタートしてそこの議論に立脚してこのような考えが出ている、ということを説明したらいいんじゃないか(大変ですが。。)
10:52 AM
要するにそれは誤解である、と。
Avatar
そうなんだけど、そのためには、既存のプロポーザルがなぜ微妙で、やり直したいか、って論拠が必要ですよね。
Avatar
Kishikawa Katsumi 1/28/2020 10:54 AM
必要だと思います。なんでブレークダウンして個別に考えた方がいいのか、ってことの理由だと思うので。
Avatar
そうですね。
Avatar
@DevAndArtist No. Before I created this thread, I discussed the proposal of the thread with my colleague and during the discussion I noticed that variadic generics can be broken down into small steps. It was just an idea and I was not sure if it was a good approach. It is a...
12:41 PM
@Yuta Saito ありがとう!直しました。
😋 1
Avatar
with my colleagueだとそれがおもちさんであると言うのが理解できない気がしました。
Avatar
my colleague が誰であるかが重要だということですか? (edited)
Avatar
リンク先がおもちさんの投稿だったので、元々の議論からの派生だということが分かりやすくなって良いかと思ったんですが、まあどっちでもいいか。
Avatar
I agree it’s worth linking to the other thread in this OP, but I disagree that “this town is too small for all of these threads” or that we as a community need to put all of our eggs in one basket or else never make any progress. I have been following the other thread and I still welcome this view on how to break down the feature conceptually.
https://forums.swift.org/t/three-steps-to-variadic-generics/33154/6 比喩が多くて賛成してるのか反対しているのかよくわからない・・・。 " I disagree ... that we as a community need to put all of our eggs in one basket" だからスレッド分けてもいいじゃないって言ってるのかな?
(edited)
And that‘s my point. You‘re proposing to push the topic forward, yet you have your own vision of this whole feature and do not consider that you could block further generalized designs. No offense though. ;)
Avatar
スレッドの分け方で消費しないで中身見ようぜ、と言ってるように見えました。
3:12 AM
一応ちょうど今日メにいるのでネイティブ勢に聞いてみます
🙏 1
Avatar
ネイティブ勢に聞いたら違うかったw 「元スレは話題が増えすぎると進捗できなくなるから、新しいスレッドを作るのがいいと思うぜ」とのこと。
3:57 AM
むっっっっず
Avatar
omochimetaru 1/29/2020 4:19 AM
Adrianさんの英語むずかしいね
Avatar
ありがとうございます。 Forum で英語で話すのむずいと思ってましたが、技術の話してても、きっと議論は技術英語じゃないからむずいんですね・・・。
5:33 AM
@omochimetaru これは Adrian さんじゃなくて Mathew さんだね。
Avatar
omochimetaru 1/29/2020 5:33 AM
ああ
Avatar
↓これ確かにできるんだけど、特殊化がきつい気がする。再帰関数を再帰インライン展開することとかあるのかな? // as pseudo syntax. func squares<(T: Numeric)...>(of values: T...) -> (T...) { switch values { case (): return () case let (t, ts...): return (t * t, squares(ts)...) } } (edited)
5:37 AM
再帰インライン展開自体は世の中に存在するのか。 Swift にはあるのかな。 https://stackoverflow.com/questions/190232/can-a-recursive-function-be-inline
inline int factorial(int n) { if(!n) return 1; else return n*factorial(n-1); } As I was reading this, found that the above code would lead to "infinite compilation" if not handled by compi...
Avatar
omochimetaru 1/29/2020 5:41 AM
C++はTMPでできますね ループが無いからだいたい再帰だし
5:42 AM
通常の関数の最適化は知らないです
5:43 AM
Swiftの場合自己再帰が無限ループしてる時の診断はありましたね
Avatar
@swift-5.1.5 func factorial(of n: Int) -> Int { if n <= 1 { return 1 } else { return n * factorial(of: n - 1) } } print(factorial(of: 5))
Avatar
120
Avatar
swiftc -O -emit-ir recursive-inlining.swift | cat
5:54 AM
define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 { entry: %2 = load %swift.type*, %swift.type** @"$ss23_ContiguousArrayStorageCyypGML", align 8 %3 = icmp eq %swift.type* %2, null br i1 %3, label %cacheIsNull.i, label %"$ss23_ContiguousArrayStorageCyypGMa.exit" cacheIsNull.i: ; preds = %entry %4 = tail call swiftcc %swift.metadata_response @"$ss23_ContiguousArrayStorageCMa"(i64 0, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @"$sypN", i64 0, i32 1)) #5 %5 = extractvalue %swift.metadata_response %4, 0 %6 = extractvalue %swift.metadata_response %4, 1 %7 = icmp eq i64 %6, 0 br i1 %7, label %is_complete.i, label %"$ss23_ContiguousArrayStorageCyypGMa.exit" is_complete.i: ; preds = %cacheIsNull.i store atomic %swift.type* %5, %swift.type** @"$ss23_ContiguousArrayStorageCyypGML" release, align 8 br label %"$ss23_ContiguousArrayStorageCyypGMa.exit" "$ss23_ContiguousArrayStorageCyypGMa.exit": ; preds = %entry, %cacheIsNull.i, %is_complete.i
5:55 AM
↓続き %8 = phi %swift.type* [ %2, %entry ], [ %5, %is_complete.i ], [ %5, %cacheIsNull.i ] %9 = tail call noalias %swift.refcounted* @swift_allocObject(%swift.type* %8, i64 64, i64 7) #1 %10 = getelementptr inbounds %swift.refcounted, %swift.refcounted* %9, i64 1 %11 = bitcast %swift.refcounted* %10 to <2 x i64>* store <2 x i64> <i64 1, i64 2>, <2 x i64>* %11, align 8 %12 = bitcast %swift.refcounted* %9 to %swift.bridge* %13 = getelementptr inbounds %swift.refcounted, %swift.refcounted* %9, i64 2 %14 = tail call swiftcc i64 @"$s4main9factorial2ofS2i_tF"(i64 5) %15 = getelementptr inbounds %swift.refcounted, %swift.refcounted* %9, i64 3, i32 1 %16 = bitcast i64* %15 to %swift.type** store %swift.type* @"$sSiN", %swift.type** %16, align 8 %._value = bitcast %swift.refcounted* %13 to i64* store i64 %14, i64* %._value, align 8 tail call swiftcc void @"$ss5print_9separator10terminatoryypd_S2StF"(%swift.bridge* %12, i64 32, %swift.bridge* inttoptr (i64 -2233785415175766016 to %swift.bridge*), i64 10, %swift.bridge* inttoptr (i64 -2233785415175766016 to %swift.bridge*)) tail call void @swift_release(%swift.refcounted* %9) #1 ret i32 0 }
5:55 AM
%14 = tail call swiftcc i64 @"$s4main9factorial2ofS2i_tF"(i64 5) だし、インライン展開されてる感じはない?
5:59 AM
@inline(__always) 付けたけど結果変わらなかった。 @inline(__always) func factorial(of n: Int) -> Int { if n <= 1 { return 1 } else { return n * factorial(of: n - 1) } } print(factorial(of: 5))
Avatar
omochimetaru 1/29/2020 6:02 AM
mainでは無くて、factorialのコンパイル結果は?
Avatar
factorial の declaration-site では再帰回数がわからないから展開できなくない?
6:05 AM
; Function Attrs: nounwind define hidden swiftcc i64 @"$s4main9factorial2ofS2i_tF"(i64) local_unnamed_addr #2 { entry: %1 = icmp sgt i64 %0, 1 br i1 %1, label %2, label %8 ; <label>:2: ; preds = %entry %3 = add i64 %0, -1 %4 = tail call swiftcc i64 @"$s4main9factorial2ofS2i_tF"(i64 %3) %5 = tail call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %0, i64 %4) %6 = extractvalue { i64, i1 } %5, 0 %7 = extractvalue { i64, i1 } %5, 1 br i1 %7, label %10, label %8
Avatar
omochimetaru 1/29/2020 6:05 AM
ループになったりしてるかなと思って。
6:07 AM
なんもないな
6:07 AM
LLVMだけでもできそうな最適化だけどそうでもないんだなあ
Avatar
S4TF内にこんなのがあるんですがこういうのもVariadic Genericsで対応してほしいところ。 (元トピック読んでないのでこういうパターンが議論されてるかは知らない) @differentiable func sequenced<L1: Layer, L2: Layer, L3: Layer, L4: Layer, L5: Layer, L6: Layer>( through l1: L1, _ l2: L2, _ l3: L3, _ l4: L4, _ l5: L5, _ l6: L6 ) -> L6.Output where L1.Input == Self, L1.Output == L2.Input, L2.Output == L3.Input, L3.Output == L4.Input, L4.Output == L5.Input, L5.Output == L6.Input https://github.com/tensorflow/swift-apis/blob/2cab4dba9889c354c941234f990e1bbab0ca5e5c/Sources/TensorFlow/Layer.swift#L210-L215
Swift for TensorFlow Deep Learning Library. Contribute to tensorflow/swift-apis development by creating an account on GitHub.
Avatar
omochimetaru 1/29/2020 7:06 AM
パラメータ間の制約なるほど
Avatar
Variadic generics are basically some small part static metaprogramming facilities, which means it won‘t scale if you try to build it with existing features as we don‘t have any static metaprogramming features yet (besides property wrappers maybe). Variadic packs (basically variadic values variadic T), are similar to tuples but they are not tuples at all. For variadic generics we would need an ability to iterate on variadic packs and also on the variadic type and tell the compiler statically how to generate type safe (boilerplate) code for us.
一般的に variadic generics がメタプログラミングの領域なのはそうとして、今提案してるのってそれをコンパイル時じゃなくて実行時でも扱えるようにするという話と言えるかも。一般的な型パラメータと同じように扱って、実行時にも扱えるし、特殊化によってコンパイル時にも解決できるようにする。それって C++ のテンプレートと Swift のジェネリクスの関係を考えたら自然なマッピングじゃないかな?
12:38 PM
@t.ae こういうのが扱える構文は必要になるよね。
Avatar
TMP に限らず、 C++ のテンプレートってコンパイル時に解決されるという認識なんだけどそれは正しい??
Avatar
Kishikawa Katsumi 1/29/2020 2:06 PM
はい、C++ のテンプレートはコンパイル時に解決されます。
2:10 PM
C++がそういう仕組みを持ってないというのもあるけど、実行時にGenericパラメータのTが、みたいなものを評価してとかはできないです。
🙏 1
2:12 PM
バイナリ配布されたライブラリだったらコンパイルしたときに使われなかった型も使えない。
Avatar
omochimetaru 1/30/2020 1:28 AM
Swiftのジェネリクスも、テンプレート的に見れば静的にはTのところにIntとかが書かれたコードを生成する機能なので、そうだと思います
Avatar
Kishikawa Katsumi 1/30/2020 5:52 AM
func viewDidLoad() { ... var previewSwipeDismiss: PreviewSwipeDismiss = .none { didSet { guard oldValue != .none else { return } if previewSwipeDismiss == .none { self.setupPreviewModeRegular() // reset to regular size self.timeScrubberView.isUserInteractionEnabled = true self.showPlayerControl() } } } ... } ^ ローカル変数のdidSetを使ったコードを久しぶりにみたけどやっぱりRetain Cycleを起こしてたので、便利なんだけど要注意って感じの書き方だなあ。 didSet { [weak self] って書けたらいいのかな?
Avatar
これviewDidLoad抜けるときに破棄されるんじゃないんですか?
Avatar
previewSwipeDismissがループしてませんか
Avatar
Kishikawa Katsumi 1/30/2020 5:58 AM
あれ、条件はこれだけじゃないんだっけか。
Avatar
didSet内でpreviewSwipeDismissを参照してる部分ですよね?ここでリークするんですか?
5:59 AM
@swiftbot class Test { var value: Int init(_ value: Int) { self.value = value } deinit { print("deinit") } } do { var x: Test = Test(0) { didSet { print("did set \(x)") } } x = Test(1) print("exit do") } print("End")
Avatar
swiftbot BOT 1/30/2020 5:59 AM
Author icon
t.ae
class Test { var value: Int init(_ value: Int) { self.value = value } deinit { print("deinit") } } do { var x: Test = Test(0) { didSet { print("did set \(x)") } } x = Test(1) print("exit do") } print("End")
Version:
swift-5.1.3-RELEASE
Output:
did set main.Test deinit exit do deinit End
Error:
Avatar
あれ、違うか
Avatar
こういうことですよね?(循環参照になるならdo抜けるときのdeinitが呼ばれないはず) (edited)
Avatar
Kishikawa Katsumi 1/30/2020 6:00 AM
ちょっと最小構成を考えてみます。 Retain Cycleを起こすのはdidset内のselfですね。
6:06 AM
前にも同じこと相談して、そのときも単にローカル変数のdidSetだけじゃないよ、ってなったのを見返しました。
Avatar
省略した箇所でpreviewSwipeDismissがループしてる予感
6:07 AM
エスパーだったw
Avatar
Kishikawa Katsumi 1/30/2020 6:07 AM
続きがあって previewViewContainer.panGesture(failForSwipe: false, delegate: self) .sink { [weak self] (gesture) in guard let self = self else { return } switch gesture.state { case .began: ... case .changed: ... if delta > 40 && velocity.y > 300 { // quick swipe print("swipe down dismiss") previewSwipeDismiss = .down } else if previewView.frame.minY < -self.view.bounds.height*0.25 { print("swipe up dismiss") previewSwipeDismiss = .up } else { previewSwipeDismiss = .none }
Avatar
これはループしますね
Avatar
Kishikawa Katsumi 1/30/2020 6:07 AM
^ これと組み合わさるとRetain Cycleが起こるんですね。。
Avatar
previewSwipeDismiss -> self -> recognizer -> pre....
6:09 AM
ローカル変数ではなく、正しくclassのフィールドにしてweak self経由でアクセスすると解決します
Avatar
Kishikawa Katsumi 1/30/2020 6:10 AM
そうですねえ。ただきっとフィールドに昇格させたくはなかったんでしょうね。 ここでしか使ってないので。
Avatar
previewSwipeDismissに予めweak selfを渡す構造にすれば
6:11 AM
ローカル変数でも動きそう
6:11 AM
どっちの方が良いかは…
Avatar
Kishikawa Katsumi 1/30/2020 6:14 AM
難しいところですね。このコードに関していうと、このGestureのSwitchめっちゃ長いのでここでいろいろやるのやめて、Viewの方に移すべきだなと考えています。
6:14 AM
そしたらpreviewSwipeDismissのdidSetのトリガーがいるとしてもフィールドにしてしまって自然になるはず。。
Avatar
適切にコンポーネント分割するならそうなりそうですね
Avatar
Kishikawa Katsumi 1/30/2020 6:19 AM
とりあえず応急処置としてweak selfを渡すコードでPRして、それで直るけどそのPRに書いたテキストはだいぶ間違ってたということになります😅どうもありがとうございました。
Avatar
↓このあたりで variadic pack と variadic tuple について Core Team メンバーが議論してたっぽいです。 https://forums.swift.org/t/starting-to-implement-variadic-generics/21159/16
Oh yes, very good point. Does this mean that variadic parameter packs will be "what tuples should have been"? Variadic parameter packs don't need to be varargs (in the current sense) so that is one bit of complexity they wouldn't have to eat. I think the only other things ...
5:08 PM
Doug Gregor, Chris Lattner, Joe Groff, John McCall の四人が議論してる・・・。
Avatar
omochimetaru 1/31/2020 4:26 AM
↑のスレッドの会話を読んだけど、たしかに実行時表現は気にしている(C++のようなテンプレート展開だけの方針は無い前提)けど
4:26 AM
あくまで型パラメータに渡されるメタタイプの表現を配列的なものにするところだけで
4:27 AM
tupleのmapみたいな事をやろうとしたときのクロージャの表現とかは
4:27 AM
直接的な言及はなさそうな気がする
4:28 AM
コアチームがどこまでの事をできるようにするつもりなのか気になるなあ。
4:28 AM
あ、でも、ラトナーがタプルの要素数とか動的に取れないとねとか書いてたな
Avatar
思ったんだけど、タプルの map 等のクロージャの表現って新しいものを追加しなくても、↓みたいな関数でも同じことになってないかな? func squares<T: Numeric>(of values: [T]) { values.map { $0 * $0 } }
4:29 AM
このクロージャの型、実行時まで決まらないよね?
Avatar
omochimetaru 1/31/2020 4:33 AM
確かにそうか。
4:34 AM
掛け算をすることは決まってるけど実際のT は呼ばれるまで固定できないから、 ジェネリックシグネチャを受け取っているはずなのか
Avatar
うん。タプルの map を実行時に取り扱うやつ、軽くお試し実装できたりしないかなと思ってるんだけど、コンパイラの中身全然わかってないけど、メソッド風構文を採用するならパーサは通ると思うから、 Sema あたりで軽くいじってできたりしないかな? (edited)
Avatar
omochimetaru 1/31/2020 4:39 AM
func squares<T: Numeric>(of values: [T]) { values.map { (a) in a * a } }
4:39 AM
// closure #1 in squares<A>(of:) sil private @$s2c17squares2ofySayxG_tSjRzlFxxXEfU_ : $@convention(thin) <T where T : Numeric> (@in_guaranteed T) -> @out T {
4:40 AM
たしかにclosureはジェネリックシグネチャを受け取ってた。
4:45 AM
Sema あたりで軽くいじって
固定長タプルだけなら、.map の型チェックの前に、AST変形かけたらいけるような気もする
4:46 AM
レシーバの型に推論が必要な場合は難しいと思う。
Avatar
固定長タプルだけなら静的に全部展開できるんだけど
4:46 AM
それだと variadic generics の下請けにならないから
Avatar
omochimetaru 1/31/2020 4:47 AM
「Tはmapメソッドが呼び出せる」って制約を推論器で扱わないといけない
4:47 AM
けどタプルはnominalじゃないからメソッドが生えてないし、ましてや特別な扱いのメソッドだから
Avatar
固定長タプルでもサイズ不定のように扱って、↑の [T]map と同じように扱えないかなぁと。それがあれば、その上に variadic generics 乗せられると思うんよね。
4:49 AM
タプルはnominalじゃないからメソッドが生えてないし、ましてや特別な扱いのメソッドだから
タプルに map 呼び出したときだけ裏口ですり抜けさせるとか、エラーとされたところでハンドルして復活させるとかでできないかな?
Avatar
omochimetaru 1/31/2020 4:49 AM
タプルに map 呼び出したときだけ
それができるのが、レシーバの型がタプルだとわかってるときってことです。
4:50 AM
例えば、 (1, "hello").map { $0.description }
4:50 AM
↑こういうコードだったら、mapのレシーバが (Int, String) のタプルである事自体が (edited)
Avatar
うん
Avatar
omochimetaru 1/31/2020 4:50 AM
この式全体の推論対象として含まれてるから
4:51 AM
裏口にすり抜けさせる前にエラーが出るかも?
Avatar
その推論の過程でレシーバに対してメソッドを探すよね?そこに裏口を作れないかな?
Avatar
omochimetaru 1/31/2020 4:52 AM
うーんまあ、この例だったらtupleにはなってるかな。
4:53 AM
まあそれはできそうですね。
Avatar
レシーバとメソッドの組み合わせを探索するのかな?どちらにしても、そこでタプルと map の組み合わせをパスさせる。
Avatar
omochimetaru 1/31/2020 4:54 AM
で、まあ、コード変形でやらないんだとしたら
4:55 AM
ASTに対して型付けが終わった状態になるようにして、verifier的なものも、回避するショートカットを差し込んで
4:55 AM
次のSIL生成でやる感じかな。
4:57 AM
固定長タプルでもサイズ不定のように扱って
↑ここが微妙で、「可変長タプル」の内部表現が無いから、SILの式が構築できないような気がする。
Avatar
これって結局 <T: Numeric>[T] のようなものになると思うんだけど
5:01 AM
さっきの func squares<T: Numeric>(of values: [T]) { values.map { (a) in a * a } }T が特殊化されないときの [T] のように扱えないかな?
Avatar
omochimetaru 1/31/2020 5:06 AM
実行時モデルとしてそのように扱う基盤はあると思うけど
5:07 AM
SILコードは基本的に全部SIL型システムで型付けされた命令列として構築されるから
5:07 AM
少なくとも可変長タプルを型として追加しないとどうにもならない気がする
Avatar
SIL レベルでは追加が必要で、 LLVM-IR にするときに既存の仕組みにできるかもってこと?
5:08 AM
SIL の型システムでは扱えないと。
Avatar
omochimetaru 1/31/2020 5:08 AM
そうですね。
Avatar
なるほど。
Avatar
omochimetaru 1/31/2020 5:08 AM
あーまあ、 [Any] にしちゃえば
Avatar
それは考えたんだけど、その実装あまり説得力がなさそうだなとw
Avatar
omochimetaru 1/31/2020 5:08 AM
なんか無理やり組み上げられる気もするけど・・・
5:09 AM
まあでも「可変長タプルを追加して固定長タプルをそれにアップキャストする」のと 「固定長タプルを [Any] にアップキャストする」のは
5:09 AM
本質的にあまり変わらない気がする。
5:10 AM
の T が特殊化されないときの [T] のように扱えないかな?
↑このレベルの観点ならまさにそういう話なような。
Avatar
本質的にはそうかもしれないけど、ぎりぎりの緩さで留めておかないと説得力がないかなと。
Avatar
omochimetaru 1/31/2020 5:18 AM
うーん?仮に実装できたとして、それをもって何を主張したいんですか? (edited)
Avatar
Variadic generics are basically some small part static metaprogramming facilities, which means it won‘t scale if you try to build it with existing features as we don‘t have any static metaprogramming features yet (besides property wrappers maybe). Variadic packs (basically variadic values variadic T), are similar to tuples but they are not tuples at all.
5:21 AM
とのことなので、既存の仕組み(かそのちょっとした拡張)の上でタプルと共通化して実現できるよと言えるかなと。
5:22 AM
TMPみたいな方式として導入するよりも、ジェネリクスとテンプレートの関係を考えたら、ジェネリクスみたいに動的にも扱われる仕組みとした上で特殊化もできるという方が Swift に馴染むと思うんだけど。 (edited)
Avatar
omochimetaru 1/31/2020 5:25 AM
うーん?AdrianさんはC++みたいな静的展開機能を前提に考えてるのかな?
5:26 AM
さっきの「Starting to implement Variadic Generics」のスレだと
5:26 AM
コアチームの人たちはジェネリクスみたいな動的な仕組みを前提に会話してるように見えたけど。
5:26 AM
ラトナー This could allow a more dynamic model for variadics that might fit better into the overarching swift design than the static C++ model.
(edited)
5:27 AM
StaticなC++方式じゃなくて、動的な方式がSwiftの設計の拡張としてフィットするって。 (edited)
5:29 AM
Douglasも At this point you can write something like: struct Tuple<Types...> { } but not do anything with it.
5:29 AM
↑こう書いてるし、これは、可変長ジェネリクスが言語機能にあったら、タプルはそれだけで表現できる 事を言っているので
5:31 AM
うーん、このスレにもAdrianさんは居るんだよな、うーん? (edited)
Avatar
謎だね。
Avatar
omochimetaru 1/31/2020 5:38 AM
Variadic generics are not to make just tuples nice, there are more use cases which cannot be solved through tuples.
こっちが言いたい事なのかな。
5:38 AM
可変長タプルよりも可変長ジェネリクスのほうがより広くて柔軟な機能だから、 可変長タプルじゃできないことも可変長ジェネリクスだとできると。
5:39 AM
ただそれはお互いにわかってて(てか、steps to VGなんだから、包含関係はそれいがいありえない)
5:40 AM
VGがある時点で struct Tuple<Types...> でタプルは終わるし。
Avatar
うーん、前段からのつながりではメタプログラミングでやるんだって思い込みが先にあっての発言なのかなぁと思ったけど、どうなんだろうな。
Avatar
Taketo Sano 2/4/2020 4:37 AM
お悩み相談させてください🙏 自作のグラフ構造を使った計算を行おうとしているのですが,絶望的に速度が出ず悩んでいます.扱う頂点の数はかなり多く(558,661),動的に辺を追加したり外したりする処理を行います.TimeProfiler を見るとほとんどが Set や Dictionary の変更にかかっているようです. 同等の処理をしているはずの C++ ライブラリだと一瞬で計算が終わるので,かなり悲しい気持ちです.もし改善のヒントなどあればご教示頂けると幸いです🙏 ↓ こちらの main.swift を実行すればすぐみられます. https://github.com/taketo1024/SwiftyMath-knots/tree/graph グラフ構造(Set や Dictionary を組み合わせたシンプルな struct ) https://github.com/taketo1024/SwiftyMath-knots/blob/graph/Sources/Sample/SimpleDirectedGraph.swift グラフ処理部分 https://github.com/taketo1024/SwiftyMath-knots/blob/graph/Sources/Sample/HFKCalculator.swift こちらが高速な C++ のライブラリ https://bitbucket.org/t3m/py_hfk/src/default/hfk_class.cpp C++ のライブラリの方は頂点を std::vector で,辺を std::list で持っているようです.
4:39 AM
Swiftの値型はCoWがあってもループを伴うmutating処理などでは極端に遅くなる傾向がある
Avatar
値型というかコレクションでしょうか?
Avatar
値型そのものの性質だと認識していますが、今回は特にCollectionですかね
4:40 AM
おそらくなんですけど、 https://github.com/taketo1024/SwiftyMath-knots/blob/graph/Sources/Sample/HFKCalculator.swift#L74 ここでバッファの完全コピーが走ってしまっているのでは。 (edited)
Contribute to taketo1024/SwiftyMath-knots development by creating an account on GitHub.
4:41 AM
もう少し下にもループ内のMutatingがありますね
Avatar
CoW は言語機能ではなく、コレクションがそのように実装されているものだと認識してます。
4:42 AM
言語機能としては、 Existential のときに CoW を使うのはありますが。
Avatar
モジュール別れてるようなので@inlinableつけていくのも良さそうです。
Avatar
あー、なるほど。ジェネリクスが特殊化されてないのか。それありそう。
Avatar
あ、これは同じモジュールか (edited)
Avatar
あ、そうなのか。
4:44 AM
SimpleDirectedGraph は同じモジュールだけど、 SwiftyMath や SwiftyKnots, SwiftyHomology にジェネリックで特殊化されてないところはないのかな?
Avatar
Taketo Sano 2/4/2020 4:46 AM
4:46 AM
TimeProfiler で見る限りは specialized されてるように見えます.
Avatar
Set.insertの時間、バッファコピーされてる数値が出ていると思います
4:47 AM
593msはエグい
4:48 AM
てかその下もすごい時間かかってるなw
Avatar
総量決まってるなら先にreserveCapacityできないですか?
Avatar
Taketo Sano 2/4/2020 4:49 AM
辺は動的につけたりはずしたりするので,予測するのは結構難しそうです… 試しに一律に 800 ぐらいで reserve したら落ちましたw
😰 1
Avatar
@t.ae reserveCapacity は有効かもしれないけどオーダーまでは変わらないから CoW がうまくいかずにコピーされてしまってる方がありそう。
4:49 AM
そっち(コピー)は O(1) → O(N) になってしまうので。 (edited)
Avatar
試しにもっと大きい値でガッツリ取ってみるとどうでしょう
Avatar
@koher 以前書かれていた画像処理のライブラリで似たようなパフォーマンスの問題があったような記憶があるんですが、そのときはどうされたんでしたっけ。
Avatar
すみません、何も記憶がないです😅
😂 1
😩 1
5:01 AM
@Taketo Sano 僕の環境でリポジトリを clone して swift run -c release すると(コンパイル後)一瞬で結果↓が表示されるんですが、これはおかしいですか? 3_1 j\i -3 -2 -1 0 -1 𝐙 -3 𝐙 -5 𝐙 -7 𝐙₂ -9 𝐙 (edited)
Avatar
Taketo Sano 2/4/2020 5:02 AM
あらっ
Avatar
あ、ブランチが
Avatar
Taketo Sano 2/4/2020 5:02 AM
それは master か develop branch だと思います。 graph っていう branch がありませんか?
Avatar
graph じゃないといけないのか
Avatar
Taketo Sano 2/4/2020 5:03 AM
さようでございます🙏
Avatar
Taketo Sano 2/4/2020 6:34 AM
6:35 AM
ただの subscript.getter でめちゃくちゃ時間かかってるんで,単純に巨大な collection は swift に不向きということなんですかね…😞
Avatar
GridComplex.Generatorのハッシュ関数とEquatableがかなり重いですねこれ
6:45 AM
Contribute to taketo1024/SwiftyMath-knots development by creating an account on GitHub.
Avatar
Taketo Sano 2/4/2020 6:48 AM
hash は Int 型の値を一個 combine してるだけなので重いはずはなさそう…
6:52 AM
extension で struct 定義してるからとか?
Avatar
もしかして、これって複数回呼び出した累計の時間で計測されてます?
Avatar
Taketo Sano 2/4/2020 6:56 AM
多分そうだと思います(あまり TimeProfiler の見方わかってないですが…)
Avatar
Hasherは1個だけだと使う意味なさそうなので直接hashValue返してもいいかも。
Avatar
Taketo Sano 2/4/2020 7:03 AM
https://github.com/apple/swift/blob/master/stdlib/public/core/Hashable.swift func _rawHashValue(seed: Int) -> Int これを実装しとけばいいんですかね🧐
Avatar
おお、今の定義ってそうなってたんですね…そうするとそこは原因じゃないか…
Avatar
omochimetaru 2/4/2020 7:09 AM
7:09 AM
👀 1
7:09 AM
7:11 AM
こんな感じでボトルネックはgraph.connectの中のDictionary.subscriptとSet.insertなんですが
7:11 AM
CoW由来のコピーコストが掛かってる雰囲気のトレースではないんですよね
7:12 AM
Set.insertの40%が参照カウント操作なのは気になる
7:15 AM
forループの対象がSetで、そのSetに対するinsertがconnectの中で生じるから、参照共有されてコピーされる気はしたんだけど、何が起きてるかイマイチわからん
7:16 AM
😫 1
7:17 AM
connectの中のDictionary.subscriptの方は、52% mallocが食ってる。
Avatar
intoなreduceにすれば改善するとか有りえますかね
Avatar
Taketo Sano 2/4/2020 7:17 AM
むむむ…
Avatar
omochimetaru 2/4/2020 7:21 AM
reduce
僕にはよくわからん
7:22 AM
この2重ループって
7:22 AM
a in cotargetsとb in targetsをconnectしてるから
Avatar
Taketo Sano 2/4/2020 7:23 AM
graph 関数をパラレルで走らせてるのが関係あったりしますかね?
Avatar
omochimetaru 2/4/2020 7:23 AM
その時の書き換えは targets[a] << b と cotargets[b] << a だから、 かみ合わせがズレてるから同じSetはほぼ操作しないですよね?
7:24 AM
ん、ちがうな
7:24 AM
yとxも出てくるのか
7:26 AM
graph 関数をパラレル
graph()が大本で並列になってる件ですよね、それ自体は関係ないはず
7:26 AM
処理が完全に垂直(?)分割されてるので相互作用しない (edited)
👌 1
Avatar
Taketo Sano 2/4/2020 7:27 AM
x -> y という頂点の組と辺をセットで消すんですけど,その際に a -> y なる 全ての a に対して,x から生えてる辺を mod 2 で足す,ということをしてます.
7:28 AM
a, x の両方から繋がってる b は辺を消して,x のみ x -> b となってる場合は a -> b とつなぎ直す,という.
7:29 AM
Generator 型で index されてるのが問題なのかと思って,さっき Int-indexed に書き換えてみましたが,それでも速度は変わりませんでした.
7:31 AM
let A = graph.cotargets[y] ?? [] let B = graph.targets[x] ?? [] for a in A where a != x { for b in B where b != y { if graph.targets[a]?.contains(b) ?? false { graph.disconnect(a, b) } else { graph.connect(a, b) } } } こういう風に A, B を外に出すのも試してみたけど変わりません…
Avatar
omochimetaru 2/4/2020 7:36 AM
a -> b とつなぎ直す時の targets[a]とcotargets[b]は、 イテレートされてる cotargets[y] と targets[x]とは別のSetだから
7:36 AM
やっぱりコピーは起きない気がするな。
Avatar
Taketo Sano 2/4/2020 7:36 AM
はいー🙄
7:36 AM
そんなに非常識なことをしてるコードじゃないと思うんですけどねぇ…
Avatar
omochimetaru 2/4/2020 7:36 AM
そうですね
7:37 AM
僕もなんかパフォーマンス頭打ちになったときDictionaryとかSetのこんな感じのプロファイルになった事あって
7:37 AM
参照カウント処理の割合が高くてウームとなった
Avatar
Taketo Sano 2/4/2020 7:37 AM
ウーーーム
7:38 AM
この計算対象は grid-number = 11 に対応するものなんですが,10 の場合は割とすんなり終わるんですよね.
Avatar
omochimetaru 2/4/2020 7:38 AM
10の場合の11倍ぐらい重い感じ?
Avatar
Taketo Sano 2/4/2020 7:38 AM
main で let G = GridDiagram.load("11n37")! としたのがそれです.
7:39 AM
いえ,3秒ぐらいで終わりますw
7:39 AM
N = 11 になった瞬間にシンギュラリティがw
Avatar
omochimetaru 2/4/2020 7:39 AM
なるほどw
Avatar
Taketo Sano 2/4/2020 7:40 AM
(まぁ N だけで計算量が決まる訳ではないんですが,一つの目安として)
Avatar
omochimetaru 2/4/2020 7:40 AM
graph() のうち malloc: 23%, retain: 35%, release: 34% (edited)
7:41 AM
N=10の場合のセットアップ教えてもらえますか?
7:42 AM
ん?もう10か
7:42 AM
let G = GridDiagram.load("10_152")!
7:43 AM
10_152 でも全然3分以上かかる。
Avatar
Taketo Sano 2/4/2020 7:45 AM
10_152 は N = 11 のケースです(ややこしいですが)
7:45 AM
11n37 が N = 10 です.
Avatar
omochimetaru 2/4/2020 7:46 AM
なるほど、そこは逆なのか。
Avatar
Taketo Sano 2/4/2020 7:46 AM
( 11n とかについてる数字は結び目の交点数というもので,今の N は GridNumber というまた別の数になります) (edited)
7:47 AM
graph() のうち malloc: 23%, retain: 35%, release: 34%
何か謎のオブジェクトが生成&消滅を繰り返している…?
Avatar
omochimetaru 2/4/2020 7:50 AM
11n37: malloc: 24%, retain: 27%, release: 32% あんまりかわんないかなあ
7:51 AM
Time profilerの一番下に在る文字列検索のとこに↑入れると、今見てるビューでそれにマッチする関数が何%かわかるんですけど。
7:53 AM
mallocについては、DictionaryやSetの初回か拡張で必要な操作かもしれなくてなんとも言えなくて、 retain/releaseについては、DictionaryとかSetの内部にあるヒープオブジェクトに触る前後な気がします。
Avatar
Taketo Sano 2/4/2020 7:54 AM
なるほどー
7:55 AM
大規模なコレクション操作でいつもパフォーマンスの壁にぶつかってる感じがするので,やはりこの手の処理は Swift でやるべきじゃないのかなー😔
Avatar
omochimetaru 2/4/2020 7:56 AM
Swiftのstdlibが作りの問題で遅い説は自分の中でもフツフツとある・・・
7:56 AM
断言できるほど全体像が見えてないんですが。
Avatar
Taketo Sano 2/4/2020 7:56 AM
ぬぬぅ
Avatar
omochimetaru 2/4/2020 7:57 AM
この謎のmalloc、ストレージ用のメモリじゃなくて、coroutineスクラッチメモリか? (edited)
🐣 1
8:03 AM
8:03 AM
この2つの対応が
8:04 AM
8:04 AM
↑これのDictionary.Variant.subscript.modifyと NativeDictionary.subscript.modifyのとこ
Avatar
Taketo Sano 2/4/2020 8:05 AM
malloc はどこに対応するんです?
8:05 AM
見方が分かってません🥶
Avatar
omochimetaru 2/4/2020 8:06 AM
_modify がコルーチンになってて、コンパイラが生成するんですよね。 Variantのほうなら let cocoavar native
8:07 AM
NativeDictionaryならlet bucket, found var value のため。
8:09 AM
要するに、subscript処理の70%ぐらいが、コンパイラが差し込んでるmallocのせいなんじゃないかと・・・
Avatar
Taketo Sano 2/4/2020 8:09 AM
ふむふむ
8:09 AM
これって巨大な dictionary を作れば簡単に再現できるんですかね.
Avatar
omochimetaru 2/4/2020 8:10 AM
むしろ大きさは関係ない?
Avatar
Taketo Sano 2/4/2020 8:10 AM
バグレポ出すとして,めっちゃ遅いことを体感してもらうにはめっちゃでかいのを作る必要があるかと思いまして.
Avatar
omochimetaru 2/4/2020 8:11 AM
そうですねえ N=10 と N=11での振る舞いの違いとの関係もよくわからないけど・・・ (edited)
Avatar
Taketo Sano 2/4/2020 8:13 AM
この計算は計算量が組み合わせ的に増えるので,N が 1 増えただけでボトルネックがめっちゃ強く効いてくることはありうると思います.
Avatar
omochimetaru 2/4/2020 8:13 AM
なるほど。
Avatar
とりあえずyield入る前のSwiftでプロファイルするとどうなるんでしょう
Avatar
omochimetaru 2/4/2020 8:16 AM
入る前は、modify相当のやつは、 materializeForSet っていうアクセサだったんだよね
Avatar
プロファイルに差が出るんじゃないかと
Avatar
omochimetaru 2/4/2020 8:17 AM
どっちかかな〜と思っていて 1. materializeForSetのときもmallocしてたから同じ 2. 実はmodify化で性能低下してる、malloc→allocaは最適化を今後実装予定
Avatar
試しに走らせてみてる感じ
Avatar
omochimetaru 2/4/2020 8:18 AM
modify見える
Avatar
いますね
8:18 AM
もっと古いXcodeで走らせないとだめか
Avatar
omochimetaru 2/4/2020 8:18 AM
coroutineは1年ぐらいは仕込まれてたはず。
8:19 AM
で、バージョン下げすぎるとコンパイルが通らなそう・・・
8:23 AM
バグレポ出すとして,めっちゃ遅いことを体感してもらうにはめっちゃでかいのを作る必要があるかと思いまして.
どういうのが良いんだろうなあ。 単純に計算が複雑だから時間がかかるのではなく Swift stdlibのせいで時間が不当にかかってるという事を、 主張したい。
8:23 AM
(現状、その事実も厳密に突き止められたとも言えない
Avatar
巨大Dictionaryと小さいDictionaryを作って、insertの時間に差があるからO(1)じゃなくなってるよっていう報告でどうなんでしょ。
8:25 AM
それともサイズ関係なく遅いのが問題なのか。
Avatar
omochimetaru 2/4/2020 8:25 AM
サイズ関係ない気がする。
Avatar
キャパシティの差で如実に差が出てるんですけど、こういうもんでしたっけ
8:30 AM
名前がアレなのはアレ
Avatar
omochimetaru 2/4/2020 8:32 AM
小さい時は辞書にしない最適化が入ってるかも。
Avatar
なるほど
Avatar
omochimetaru 2/4/2020 8:32 AM
要素数が8個とかだったら、ハッシュ値の計算すらしないで
8:32 AM
全探索しちゃったほうが速いというのがある
Avatar
なんかウォームアップの時間っぽい気がしてきた
Avatar
omochimetaru 2/4/2020 8:55 AM
@Taketo Sano これC++のやつはどういうデータ構造なんですか? class Link { int graphsize; vector < vector <Int64> > Generators; vector < vector <Vertex> > Graph; }
8:56 AM
Linkの中にGraphがあるのも2次元vectorなのも謎だ
Avatar
Taketo Sano 2/4/2020 8:56 AM
これは色々と特殊で,
8:56 AM
まず Link は数学用語で,結び目が複数あるやつのことですw
Avatar
omochimetaru 2/4/2020 8:57 AM
でも、 std::mapstd::unordered_map も使ってないから、結構違う構造をしてそう
8:57 AM
Linkはデータ構造の方じゃないのかw
Avatar
Taketo Sano 2/4/2020 8:59 AM
ここで現れるグラフは階層構造があって,上から下へ辺が落ちるような形になっています.僕のプログラムで var gens = generators.group{ $0.MaslovDegree }.mapValues{ Set($0) } と分けて,上から順番に Graph に頂点を追加してるのがそれに対応します.
9:00 AM
( MaslovDegree というのがその階層,C++ コードでは MM と書かれている)
Avatar
omochimetaru 2/4/2020 9:00 AM
あ〜。
Avatar
とりあえず、単純な subscript setDictionary の要素数によるパフォーマンスの差はなさそうです。 https://github.com/koher/swift-dictionary-performance
Contribute to koher/swift-dictionary-performance development by creating an account on GitHub.
👍 1
Avatar
Taketo Sano 2/4/2020 9:01 AM
僕のコードの Generator 型に code というプロパティがありますが,これが C++ のコードで Int64 型 の Generator と対応しています.
Avatar
↓を 1 から 10_000_000 まで試した。 func testDictionary_1() { var dictionary: [Int: Int] = .init(uniqueKeysWithValues: (0..<1).map { ($0, $0 + 1) }) XCTAssertEqual(dictionary.count, 1) let count = dictionary.count measure { for i in 0..<n { let key = i % count dictionary[key] = i + 2 XCTAssertEqual(dictionary[key], i + 2) } } } (edited)
Avatar
Taketo Sano 2/4/2020 9:02 AM
ふーむ.
Avatar
あ、いちおう count の assert をしておいた方がいいな。→しました (edited)
Avatar
Taketo Sano 2/4/2020 9:02 AM
入れ子構造?特有の問題なんですかね
Avatar
Kishikawa Katsumi 2/4/2020 9:04 AM
ちなみにこれリポジトリをクローンしたあと単純に実行してどれくらい時間かかるプログラムなんですか? とりあえず実行してみてるんですけど全然終わる気配がなくて。。。
Avatar
omochimetaru 2/4/2020 9:06 AM
なるほど。 C++の方だと階層が1次のキーで、2次のキーが頂点のindex 頂点に対してstd::linkのinとoutが 上からくる辺と下に出ていく辺の、ターゲットの頂点のindexか。
Avatar
Taketo Sano 2/4/2020 9:06 AM
@Kishikawa Katsumi はい, 全然終わらないです.C++ のライブラリで対応する計算は1秒とかで終わるので悲しいのです😢
Avatar
omochimetaru 2/4/2020 9:06 AM
これって階層とか1つの階層の頂点の数って数量的にはどのくらいですか?
Avatar
Taketo Sano 2/4/2020 9:07 AM
頂点数はトータルで55万ぐらいです.
9:07 AM
階層ごとはちょっと調べてみないとわかりません.
Avatar
omochimetaru 2/4/2020 9:07 AM
なるほど。
Avatar
Kishikawa Katsumi 2/4/2020 9:07 AM
なんかもう少し短い時間で試せるように問題は変えずにデータを減らしたりしたいんですけど、それって簡単にできます?
Avatar
Taketo Sano 2/4/2020 9:08 AM
@Kishikawa Katsumi はい, main.swift で 10_152 と書いてるところを 9_42 とか 11n37 とかに変えるとすぐ終わります.
🙏🏻 1
Avatar
omochimetaru 2/4/2020 9:08 AM
if (*search == *k) { Graph[MM][*j].out.erase( search ); if( *k != target) Graph[MM-1][*k].in.remove(*j); break; } ↑この辺のerase とか removeO(N) アルゴリズムなので、 オーダーで見ると佐野さんの実装のほうが遥かに速いはずなんですが、 そうではないとすると、 一つの頂点につながる辺の数自体はたかだか100とかそんなもんなんだろうか。 (edited)
Avatar
Taketo Sano 2/4/2020 9:09 AM
@omochimetaru そうなんですよ!
9:10 AM
それをみて,Swift の方でも Array に変えてやってみたんですが,ゴリゴリ遅くなりましたw
Avatar
↑のテスト、 N によらず 10万回の subscript set and get (および剰余演算と XCTAssertEqual )が 0.1 秒くらいなんですけど、絶対値として十分に速いですか?
Avatar
なんか雑に調べてる感じ、Dictionaryそのものをパッと使ったときの性能としては、Swift.DictionaryもNSDictionaryも優位な差は無いっぽいんですよね
Avatar
Taketo Sano 2/4/2020 9:10 AM
@omochimetaru ちなみに edge のほうは vector じゃなくて list を使ってるんですよね.
Avatar
omochimetaru 2/4/2020 9:11 AM
@Taketo Sano ほんとだ。listだからこの削除はO(1) ですね。
Avatar
Taketo Sano 2/4/2020 9:11 AM
でも検索は片っ端からやってるから,そこは結構効いてくると思うんですけどねぇ. (edited)
Avatar
@koher NSMutableDictionaryと同等のスピードが出ていれば、参照型に対してスペックで劣ってるとは言えない気がしています
9:13 AM
そうか、手早く試すのにNSを入れて見るのがあった
Avatar
omochimetaru 2/4/2020 9:13 AM
そうかそうか。絞り込み検索のとこが遅いはずですね。
Avatar
Taketo Sano 2/4/2020 9:13 AM
はい😔 なのに set.contains の方が絶望的に遅いっていう😂
Avatar
omochimetaru 2/4/2020 9:14 AM
@tarunon
NSMutableDictionaryと同等のスピードが出ていれば
Dictionaryのほうが内部オブジェクトへのretain/releaseが無駄に発生して時間を食う気がしてる でも簡単なコードだと最適化でそこをスキップしたりしてるかも
9:15 AM
まあハッシュテーブルは計算量は小さくてもいろんなオーバーヘッドがでかくて、 問題の規模によっては計算量が大きい実装に負けることはあるんですよね C++のやつと同じデータ構造とアルゴリズムのコードを実装しないと、 Swift stdlibのせいで遅いとは言い切れないですね
Avatar
Taketo Sano 2/4/2020 9:16 AM
そうですねぇ…
Avatar
あれれ
9:16 AM
これやってて気がついたんですが
9:16 AM
for u in cotargets.object(forKey: v) ?? [] { targets[u]?.remove(v) } ここでArrayのオブジェクト生成する可能性ないですか? (edited)
Avatar
omochimetaru 2/4/2020 9:16 AM
ただ同じの実装するの結構大変な規模ですね。。SwiftにListねえし (edited)
Avatar
どんなコードかわからないけど、スタック的に使っているだけなら Array で代替してもパフォーマンス変わらないんじゃないかな?
9:18 AM
キューだとダメだけど。 < Listねえし
Avatar
Taketo Sano 2/4/2020 9:18 AM
いや,間に挿入したり抜いたりします.
Avatar
omochimetaru 2/4/2020 9:18 AM
↑で書いたとおり O(1) の削除をやってますね
Avatar
それだと連結リストでも O(N) な気が・・・ < 間に挿入したり抜いたり (edited)
9:19 AM
O(1) の削除は、 Array の末尾追加や削除も O(1) だから
9:19 AM
先頭だけならひっくり返せばいいし、末尾だけならそのままで同じかと思った < O(1) の削除
Avatar
Taketo Sano 2/4/2020 9:20 AM
連結リストは挿入する前後で矢印を入れ替えるだけなのに対して,Array の場合はその先にある奴を丸ごと移動しないといけないから遅いんじゃないかと思います.
Avatar
omochimetaru 2/4/2020 9:20 AM
9:20 AM
↑これの、途中での挿入削除がある処理。
9:21 AM
あ、挿入は後ろだけかな?
Avatar
途中のカーソルがあるならいいけど
Avatar
末尾への挿入はメモリの再配置が発生すると配列でもO(n)になる
Avatar
カーソルがないから先頭(か末尾)からたどらないといけないから O(N) になる
Avatar
この計算回数と大きさだとそれなりに再配置発生しそうなイメージはあります
Avatar
@tarunon 末尾の挿入の1回のオペレーションならそうですが、バッファを増やすときに倍々に増やすので、ならせば O(1) になります。
Avatar
omochimetaru 2/4/2020 9:22 AM
// For every j->target, j != source for(list<int>::iterator j = Graph[MM-1][target].in.begin(); j != Graph[MM-1][target].in.end(); j++) { if( !Graph[MM][*j].alive ) continue; // For every source->k for(list<int>::iterator k = Graph[MM][source].out.begin(); k != Graph[MM][source].out.end(); k++) { // Search for j->k. If found, remove it; if not, add it. list<int>::iterator search; for(search = Graph[MM][*j].out.begin(); search != Graph[MM][*j].out.end(); search++ ) if (*search == *k) { Graph[MM][*j].out.erase( search ); if( *k != target) Graph[MM-1][*k].in.remove(*j); break; } if (search == Graph[MM][*j].out.end()){ Graph[MM][*j].out.push_back(*k); Graph[MM-1][*k].in.push_back(*j); } } }
Avatar
なるほど
Avatar
omochimetaru 2/4/2020 9:22 AM
↑検索してるところは O(N) になってますね。
Avatar
連結リストは挿入する前後で矢印を入れ替えるだけなのに対して,Array の場合はその先にある奴を丸ごと移動しないといけないから遅いんじゃないかと思います.
移動のためのコピーが速いか、連結リストで先頭からたどるのが速いかで言えば、たどる方が速い可能性はありますが、係数の差でオーダーとしてはどちらも O(N) ですね。
(edited)
Avatar
Taketo Sano 2/4/2020 9:24 AM
各 k に対して,毎回辺を全部走査してるから遅いはずなのに,
9:24 AM
どういうわけか速い😂
Avatar
omochimetaru 2/4/2020 9:24 AM
感覚的には1000個ぐらいだったら
9:24 AM
ループはめちゃ速いですよ
9:24 AM
LinkedListだとメモリ局所性が無いんでループも遅いんでそこは謎・・・
Avatar
そう、飛び飛びにたどらないといけないから、まとめてコピーの方が速い可能性もあるかなと。
Avatar
Taketo Sano 2/4/2020 9:27 AM
なるほどー
9:27 AM
(帰宅のため一旦抜けます,色々調べて下さってありがとうございます)
Avatar
omochimetaru 2/4/2020 9:28 AM
@Taketo Sano
それをみて,Swift の方でも Array に変えてやってみたんですが,ゴリゴリ遅くなりましたw
これは、今の SimpleDirectedGraph の中身の実装だけSetからArrayに変えたってことですよね?
(edited)
Avatar
Taketo Sano 2/4/2020 9:28 AM
はい、edge のとこを配列にしました。
Avatar
omochimetaru 2/4/2020 9:28 AM
了解です。
Avatar
Taketo Sano 2/4/2020 9:29 AM
find して remove
Avatar
omochimetaru 2/4/2020 9:30 AM
@tarunon
ここでArrayのオブジェクト生成する可能性ないですか?
あるけど、空のArrayって専用の型があって内部最適化されてるからあんまり気にしなかった
Avatar
Taketo Sano 2/4/2020 9:30 AM
Generator は順序をつけることができるので、sortedarray にすれば速くなるかなと思ったりはしました。
Avatar
>空 naruhodo
Avatar
```swift for u in cotargets.object(forKey: v) ?? [] { targets[u]?.remove(v) } ```
空 Array の問題はないにしても、 if let で書き換えた方が良さそうな気が。
9:50 AM
ん?てか targets[u]?.remove(v) これコピー発生しませんか?↓になって Set が二重に存在しない? var ids: Set<Id>? = targets[u] ids?.remove(v) targets[u] = ids (edited)
Avatar
omochimetaru 2/4/2020 9:50 AM
↑で16:09に貼った画像のとおりで、 connect が最大のホットスポットなんですよね
9:51 AM
そこは、そうならない、subscriptに対するmodifyアクセスになるから。
Avatar
内部実装をNS使って参照型に書き換えてみたんですけど、速くなったようには見えない。
Avatar
omochimetaru 2/4/2020 10:02 AM
時間どのくらい変わった?
Avatar
終わらンゴ
10:02 AM
テストケースは全部通過するのを確認しています。
Avatar
omochimetaru 2/4/2020 10:02 AM
終わらんケースだと比較にならないっしょ
10:03 AM
@Kishikawa Katsumi はい, main.swift で 10_152 と書いてるところを 9_42 とか 11n37 とかに変えるとすぐ終わります.
↑これで比較すると良いと思う
Avatar
ok
10:03 AM
そしてプロファイルは強制終了してしまうようになったんですよね
Avatar
omochimetaru 2/4/2020 10:04 AM
計測は $ time .build/release/SwiftyKnots-Sample が良いと思う
Avatar
あーなんか
Avatar
Kishikawa Katsumi 2/4/2020 10:04 AM
^ 同じことやったんですけど変わらないかむしろ遅くなる感じがあります。
Avatar
ですよね
Avatar
Kishikawa Katsumi 2/4/2020 10:05 AM
そして要素が少ないとたぶん問題が変わるような印象。
10:05 AM
遅いのってメモリアロケーションが大量だからじゃないかな?
Avatar
omochimetaru 2/4/2020 10:05 AM
そこがわからない 10_152 が11n37に比べてどのくらい爆発的に問題を膨らませているのかが・・・
Avatar
Kishikawa Katsumi 2/4/2020 10:06 AM
^ データ構造もあると思いますけど、要因の1つとして。
Avatar
omochimetaru 2/4/2020 10:06 AM
可能性はありますね。
Avatar
Kishikawa Katsumi 2/4/2020 10:06 AM
みてると元のコードは15GBくらいメモリ使う(たぶんもっと増える)ので。
Avatar
omochimetaru 2/4/2020 10:07 AM
マジか。
Avatar
Kishikawa Katsumi 2/4/2020 10:07 AM
NSSetとかにすると減るんだけどそれでも7GBくらい使ってた。
10:07 AM
なんかリニアに使うメモリが増えてくように見えました。
Avatar
omochimetaru 2/4/2020 10:08 AM
10:08 AM
↑シングルスレッドに改造してて1.57Gだ。たしかに4並列ならそのくらいになってそう。
10:09 AM
確かにそこまで行くとmallocが重くなっちゃってあちこち重くなるのがありそう
Avatar
今のケースに近いような [Int: Set<Int>] に変えて insert するようにしたら、 Set の N が大きくなると激遅に・・・。 func testDictionary_10_000_000() { let count = 10_000_000 var dictionary: [Int: Set<Int>] = .init(uniqueKeysWithValues: (0..<100).map { ($0, Set(0..<count)) }) XCTAssertEqual(dictionary.count, 100) XCTAssertEqual(dictionary[0]!.count, count) measure { for i in 0..<n { let key = i % 100 dictionary[key]?.insert(i) XCTAssertTrue(dictionary[key]!.contains(i)) } } }
Avatar
omochimetaru 2/4/2020 10:35 AM
ほお
Avatar
Dictionary の要素数は 100 固定で、 Set の要素数だけ変えてる。
10:35 AM
やっぱコピー走ってないかな?
Avatar
omochimetaru 2/4/2020 10:36 AM
コピーが走ったかどうか確認する方法なにかあるかな。
Avatar
dict.remove -> insert -> dict.add にしてみる
Avatar
おぉ
Avatar
お、速くなった気がする
Avatar
omochimetaru 2/4/2020 10:39 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
10:39 AM
Setの場合、ensureUniqueってメソッドの中でcopyまたはcopyAndResizeが呼ばれるから
10:40 AM
これにブレークポイントを貼ることができればわかりそう
Avatar
(みんなすごい)
Avatar
直感通り#beginner-help-archived で収まらない解決フローだったw
🤯 1
🥳 1
10:41 AM
Swiftの関数はマングル済みの文字列でSymbolicBrakepoint貼れますよ (edited)
Avatar
omochimetaru 2/4/2020 10:41 AM
https://github.com/omochi/SwiftyMath-knots/tree/ptr とりあえず、グラフの実装をポインターベースに書き換える実験をしてみました シングルスレッドで、 11n37が 5.48sec から 3.02secになった。
Contribute to omochi/SwiftyMath-knots development by creating an account on GitHub.
10:42 AM
10_152はそもそもの元のバージョンが25分待っても終わらなかったので比較できてない。
10:43 AM
↑このバージョンだと、余計なコピーの心配は多分無いのと、subscriptアクセスの回数はかなり減らしてる
Avatar
わーぉ。10_152 は改善版でも終わらないですか?
Avatar
あれ?変わらなかった・・・。さっきのはなんだったんだ??
Avatar
omochimetaru 2/4/2020 10:44 AM
いま13分ぐらい経過だからなんとも言えない > 10_152
10:44 AM
@tarunon > Swiftの関数はマングル済みの文字列 まずlibSwiftCoreからそれっぽいの探すやつかw
Avatar
ちょっとまってて
Avatar
omochimetaru 2/4/2020 10:45 AM
デバッガシンボルトリガーでコピーが発生したらprint("copy!!")とかやってみたらいいのか。
Avatar
(C++ のライブラリだと数秒で終わるんですよね…)
Avatar
omochimetaru 2/4/2020 10:45 AM
そのオーダーの高速化はできてないですね〜
10:47 AM
数秒レベルになると、ライブラリの性能とかの次元じゃないと思うんで、なんか理由がありそうですけど・・・
Avatar
うーむ…
Avatar
ほい ss10_NativeSetV12ensureUnique02isD08capacityS2b_SitF
10:49 AM
10:49 AM
なんか余計なもんひっついてるな
Avatar
omochimetaru 2/4/2020 10:49 AM
ensureUniqueのほうじゃなくてcopyだね
Avatar
copyねおk
Avatar
omochimetaru 2/4/2020 10:49 AM
copyとcopyAndResizeの両方が居る、どっちに行くかは状況によるから。 (edited)
Avatar
_$ss10_NativeSetV13copyAndResize8capacityySi_tF _$ss10_NativeSetV4copyyyF
10:50 AM
ほい
10:50 AM
思ってたより素直なマングルだった
Avatar
omochimetaru 2/4/2020 10:50 AM
で、これを、さっきのkoherのコードで試してみると
10:56 AM
insertももらえます?
10:56 AM
あー
10:56 AM
profilerでもわかるかな
11:01 AM
なるほど specializeされてるからシンボル違った
11:05 AM
あとインライン化されてたりもする
11:06 AM
16.00 ms 45.7% 7.00 ms specialized _NativeSet.insertNew(_:at:isUnique:) _$ss10_NativeSetV9insertNew_2at8isUniqueyxn_s10_HashTableV6BucketVSbtFSi_Tg5 (edited)
Avatar
ふむ
11:06 AM
あーそうか
11:06 AM
nmをgrepするとはやいと思います
Avatar
omochimetaru 2/4/2020 11:06 AM
↑これで止めてからアセンブリステップ実行した感じでは、コピーのフローには入ってない気がした
Avatar
omochimetaru 2/4/2020 11:14 AM
[omochi@omochi-iMac-PC43 Release]$ nm Sandbox_20200204195103 | grep NativeSet 0000000100001b70 t _$ss10_NativeSetV13copyAndResize8capacityySi_tFSi_Tg5 0000000100001970 t _$ss10_NativeSetV4copyyyFSi_Tg5 0000000100001e50 t _$ss10_NativeSetV6resize8capacityySi_tFSi_Tg5 0000000100001870 t _$ss10_NativeSetV9insertNew_2at8isUniqueyxn_s10_HashTableV6BucketVSbtFSi_Tg5 [omochi@omochi-iMac-PC43 Release]$ nm Sandbox_20200204195103 | grep NativeSet | swift demangle 0000000100001b70 t generic specialization <Swift.Int> of Swift._NativeSet.copyAndResize(capacity: Swift.Int) -> () 0000000100001970 t generic specialization <Swift.Int> of Swift._NativeSet.copy() -> () 0000000100001e50 t generic specialization <Swift.Int> of Swift._NativeSet.resize(capacity: Swift.Int) -> () 0000000100001870 t generic specialization <Swift.Int> of Swift._NativeSet.insertNew(_: __owned A, at: Swift._HashTable.Bucket, isUnique: Swift.Bool) -> ()
Avatar
特にcopyは走ってない気がしますね
Avatar
omochimetaru 2/4/2020 11:15 AM
11:16 AM
こういう実験をして、insertNewは止まるけど、copy系は止まらなかった。
Avatar
あ、そうだ。_を消さないといけないのもあった。すみません
Avatar
norio_nomura 2/4/2020 11:17 AM
Xcodeのシンボリックブレークポイントは、部分一致でいけますよ。
👀 1
Avatar
omochimetaru 2/4/2020 11:25 AM
_NativeSet だけとかだと、引っかからない
11:25 AM
_NativeSet.insertNew だと、普通のメソッドは引っかかるんだけど、 specializedされた方は引っかからなかった。
11:26 AM
Avatar
norio_nomura 2/4/2020 11:32 AM
OSSツールチェインをシンボルと一緒に入れて使うと、specializedなのもいける。
Avatar
omochimetaru 2/4/2020 11:55 AM
ほう。なんでだろ・・・
Avatar
norio_nomura 2/4/2020 12:17 PM
シンボル入れてるとinline化されててもブレークポイントが効く。
Avatar
今って遅い原因が COW が走ってしまってるからかどうか検証してる感じですか?(ついていけてない)
Avatar
omochimetaru 2/4/2020 12:49 PM
そうですね ブレークする方法がわかったから
12:49 PM
元のコードでcopyが起きてるか、起きてないか、検証できる道具を得た
12:50 PM
ただまだ未確定ではあるけど、個人的にはcopyは起きていなくて他の処理が重い気がしています
12:57 PM
あ、あと、岸川さんの指摘したメモリ使いすぎはある気がします
12:58 PM
使用量が多い状態で小さいアロケートが遅くなるのかどうかは知らないですけど・・・
12:59 PM
C++実装と計算手順が対応するようにコードを書いてみて、どういう処理が何倍ぐらい遅いのかってのを突き止めていかないとわかんない気もしてます。
Avatar
Taketo Sano 2/4/2020 1:08 PM
前に作った自作 LinkedList を使ってみるのは試してみようと思います。
Avatar
omochimetaru 2/5/2020 1:35 AM
@Taketo Sano cppのhfkdemo.cppに、10_152を与える方法を教えてくださいー GridDiagramData.swiftから取れそうだけど・・・
1:36 AM
あと、11n37だと速すぎ、10_152だと重すぎるので、その間ぐらいの入力が欲しい・・・
Avatar
昨日の僕の検証はあやしかった気がします。ちゃんと確かめたいけどちょっと時間がなく・・・。 (edited)
Avatar
Taketo Sano 2/5/2020 2:16 AM
ありがとうございます,少々お待ちください.
Avatar
norio_nomura 2/5/2020 2:17 AM
とりあえずSwiftyMathのExtensionsで定義されてるAPI全部に@inlinableを付けるとヒープアロケーションがガッツリ減って、11n37が12秒台9秒台から7秒台くらいになる。 (edited)
👀 2
Avatar
Taketo Sano 2/5/2020 2:21 AM
https://bitbucket.org/t3m/py_hfk/src/default/ こちらの python package をインストールした上で, from hfk import * D = HFK([10, 9, 8, 7, 6, 5, 4, 2, 1, 3, 0], [7, 5, 6, 4, 2, 3, 1, 0, 8, 10, 9], "10_152") D.HFK_ranks() とやると計算できます.
Avatar
omochimetaru 2/5/2020 2:22 AM
hfkdemo.cppを直接触ってるので
2:22 AM
int m, a; //12n_679 //const int gridsize = 13; //int black[13] = {5,3,1,2,0,12,11,8,10,9,7,6,4}; //int white[13] = {9,6,5,4,3,1,0,2,12,11,10,8,7}; //Conway Mutant C_{2,1} const int gridsize = 11; int black[11]={10,9,3,4,5,8,6,7,1,2,0}; int white[11]={6,1,7,0,3,10,9,2,4,8,5}; //const int gridsize=12; //int black[12] = {4,1,3,7,8,9,11,2,10,6,5,0}; //int white[12] = {11,5,0,10,1,7,8,4,3,2,9,6};
2:23 AM
"10_152": {"X": [10, 9, 8, 7, 6, 5, 4, 2, 1, 3, 0], "O": [7, 5, 6, 4, 2, 3, 1, 0, 8, 10, 9]},
Avatar
Taketo Sano 2/5/2020 2:23 AM
おぉw
2:23 AM
それです,X が black で O が white です.
Avatar
omochimetaru 2/5/2020 2:23 AM
X が black で、 Owhite になればいいのか。
Avatar
Taketo Sano 2/5/2020 2:23 AM
gridSize は配列の長さです.
2:24 AM
Link::Link(int gridsize, int *black, int *white, int (*Progress)(const char *, int), bool quiet) ProgressNULL でいけると思います. (edited)
Avatar
omochimetaru 2/5/2020 2:25 AM
HFK^ ranks: 0 0 0 0 0 0 1 1 0 0 0 0 0 3 3 0 0 0 0 0 3 3 0 0 0 0 0 3 2 0 0 0 0 0 3 3 0 0 0 0 0 3 3 0 0 0 0 0 1 1 0 0 0 0 0 0
2:25 AM
↑結果のコレと
Avatar
Taketo Sano 2/5/2020 2:25 AM
おぉ,それです🙌
Avatar
omochimetaru 2/5/2020 2:25 AM
[(3, 3, 1), (1, 1, 68), (2, 2, 12), (0, 0, 244)] ↑これの対応は?
Avatar
Taketo Sano 2/5/2020 2:27 AM
これはちょっと説明が難しいです… 配列の要素 (i, j, n) は (i, j) 成分に n が入ることが対応するんですが,j >= 0 の部分だけ計算していて,さらに色々と調整をして j < 0 まで広げたものが,上に表示されてる表です.表だけだと (0, 0) がどこにあるかわからない形になってます (edited)
👀 1
Avatar
omochimetaru 2/5/2020 2:27 AM
あと、SwiftyKnotsから並列性を消したくて(途中過程の固定のため) Arrayのparallel系のextensionと、Matrixの中にあったconcurrentPerformを潰したんですけど、 まだ実行のたびに結果が変わるので、あとどこにありますかね
Avatar
Taketo Sano 2/5/2020 2:28 AM
並列処理ですか?
Avatar
omochimetaru 2/5/2020 2:28 AM
はい。あと、乱数って使ってますか?
Avatar
Taketo Sano 2/5/2020 2:28 AM
乱数は使ってないはず…
2:28 AM
並列処理もだいたいそれらを経由してるはずです.
Avatar
omochimetaru 2/5/2020 2:29 AM
ふむ
Avatar
Taketo Sano 2/5/2020 2:29 AM
上の配列だと,例えば (3, 3, 1) は (i, j) が最大のとこですが,その点における値 1 と,表の右上の数は一致します. (edited)
Avatar
omochimetaru 2/5/2020 2:29 AM
なるほど。
Avatar
Taketo Sano 2/5/2020 2:31 AM
僕の計算は,C++ のソースにある ComputeMOSRanks を計算したとこまでになってます.このあと ComputeHFKRanks に対応する計算をすると,同じ結果が得られるはずです.
Avatar
norio_nomura 2/5/2020 2:31 AM
計算してる内容が全くわからないけど、実行のたびに出力が違うのは、正しい挙動なのですか?
Avatar
Taketo Sano 2/5/2020 2:32 AM
それは間違いなく正しくないです,僕のやつではそうなってないと思いますが,一応確認します.
2:32 AM
MOS は情報が無駄に多すぎるので,それを右上から順番に削減していって, j < 0 の部分に鏡映させる感じのことをします.
2:33 AM
for(i=1; i <= gridsize-1; i++) (*HFK_Array)(m-i,a-i) -= (*HFK_Array)(m,a)*Binomial(gridsize-1,i); } }
2:33 AM
この辺がその処理
Avatar
omochimetaru 2/5/2020 2:34 AM
HFK^ ranks: 0 0 0 0 0 0 1 0 0 0 0 0 3 0 0 0 0 0 5 0 0 0 0 0 7 0 0 0 0 0 5 0 0 0 0 0 3 0 0 0 0 0 1 0 0 0 0 0 0 C++の方に11n37を入れてやったら↑が出てきたけど、 [(3, 3, 1), (2, 2, 12), (0, 0, 244), (1, 1, 68)] ↑(3,3,1)の1が右上にあるのでOKということかしら。 12, 244, 68は表には直接出てこないけど。
2:36 AM
あ〜そうか、実行結果が一定にならないのは、Dictionaryをfor-inしてる場所があるのかもな
Avatar
Taketo Sano 2/5/2020 2:36 AM
はい,11n37 は gridNumber N = 10 で,(3, 3) のところは 1 で一致していて,(2, 2) は 12 - 1 * (N - 1) = 3 で OK,(1, 1) のとこは 68 - 1 * (N - 1)(N - 2)/2 - 3 * (N - 1) = 5 で OK, ... という感じであってそうです. (edited)
2:37 AM
二項係数 nCk の分だけ右上から左下に向けて増殖してくので,それを差っ引くと正しい結果が出てきます.
2:38 AM
(*HFK_Array)(m-i,a-i) -= (*HFK_Array)(m,a) * Binomial(N-1,i); これがそれです.
Avatar
norio_nomura 2/5/2020 2:43 AM
実行のたびに出力が違う
あ、配列の要素順が違うだけだ。
Avatar
omochimetaru 2/5/2020 2:49 AM
244のところは 244 - 5x9 - 3x36 - 1x84 = 7か。
2:52 AM
let gens = generators.group{ $0.AlexanderDegree } ↑ここで戻る辞書をイテレートする順番がシャッフルされるのかな?
😆 1
Avatar
norio_nomura 2/5/2020 2:53 AM
11n37が12秒台から7秒台くらいになる。
12秒台ってのは悪いサンプルだった。@inlinableの効果は9秒台だったのが7秒台になるくらい。
Avatar
omochimetaru 2/5/2020 2:54 AM
let gens = generators.group{ $0.AlexanderDegree } let d = GridComplex( type: .tilde, diagram: gridDiagram, generators: generators ).differential let alexs: [Int] = gens.keys.sorted() let H = alexs.flatMap { (i) -> [(Int, Int, Int)] in let gens = gens[i]! return self.graph(generators: gens, differential: d) .vertices .map{ $0.MaslovDegree } .countMultiplicities() .map{ (k, n) in (k, i, n) } } print(H)
👍 1
2:54 AM
これで実行結果はいつもおなじになった。
2:58 AM
MOS ranks for non-negative Alexander grading: 0 0 0 0 0 0 1 0 0 0 0 0 12 0 0 0 0 0 68 0 0 0 0 0 244 0 0 0 Link.init(..., quiet=false) にしたら↑が出た
Avatar
Taketo Sano 2/5/2020 3:14 AM
おぉ,それは同じ結果ですね!
3:15 AM
本当にそこまでやって頂いて感謝です.
3:16 AM
はい,配列の順番が異なるのは .groupDictionary にしてるためですね.本当はこの後の処理も書いてくつもりだったのですが,計算があまりに遅いのでこの段階のものでご相談をした次第でありました💦
3:22 AM
↑よくわからないので質問を書きました (長くなったのでgist
Avatar
Taketo Sano 2/5/2020 3:41 AM
なるほど,計算の範囲がそもそも違う!?
3:47 AM
あ,いや,あってるはずです. この計算は AlexanderDegree ごとに分割することができて,僕の計算ではグラフが大きくなりすぎないように AlexanderDegree 0〜3 を分けて計算しています.CPP の方は一個のグラフにまとめて突っ込んで計算していますね(連結成分が4つあるはず) MaslovDegree の範囲も,CPP の方は MM = 13〜25 の範囲で計算がされてますが,僕のプログラムでも alex = 0 で k = -7〜5 の範囲で計算をしていて,index のつけ方が違うだけで同じ計算をしているはずです.
3:48 AM
(もともと僕の計算も一個のグラフに突っ込んでいたのですが,それだと dictionary が大きくなりすぎて遅いのかな?と思って alex ごとに分けた,という経緯があります)
3:49 AM
MaslovDegree が表における横軸,AlexanderDegree が縦軸に対応してます.AlexanderDegree ごとに分割できるという事実は,表を横に分割して行ごとに計算できるということに対応しています.
3:55 AM
HFKCalculator.run() を次のように書き換えると,CPP のと同様に Alex ごとの分割がなくなるはずです: public func run() { let d = GridComplex( type: .tilde, diagram: gridDiagram, generators: generators ).differential let H = self.graph(generators: generators, differential: d) .vertices .map { x in [x.MaslovDegree, x.AlexanderDegree] } .countMultiplicities() .map{ (deg, n) in (deg[0], deg[1], n)} print(H) } (edited)
Avatar
omochimetaru 2/5/2020 3:56 AM
ふむふむ
Avatar
Taketo Sano 2/5/2020 3:57 AM
self.graph 以降は,グラフに残った各頂点 x に対して,(x.MaslovDegree, x.AlexanderDegree) を対応させて,その個数を数え上げて表にするということをしているだけです.
4:00 AM
コードを改善しましたw
Avatar
omochimetaru 2/5/2020 5:18 AM
@Taketo Sano 最終的に扱う頂点数は同じっぽいんですが、エッジ生成の挙動が結構違うようです。 https://gist.github.com/omochi/fca8a7dc1490cfd04cf5d725e6b5bf1d
GitHub Gist: instantly share code, notes, and snippets.
Avatar
Taketo Sano 2/5/2020 5:20 AM
なるほど…! そこまで見て頂いて恐縮です🙇‍♂️
Avatar
Taketo Sano 2/5/2020 5:29 AM
(いまじっくり読んでます)
5:34 AM
とりあえず二つのコードの間で、 MM = k +20 という対応になっていて、僕のコードでは頂点がない部分をスキップするようにしているので、 CPP の方で 0 本しか生成されない頻度については無視していいファクターなはずです。
5:34 AM
辺生成の総本数が違う理由は気になる… (edited)
Avatar
omochimetaru 2/5/2020 5:38 AM
ふむふむ
Avatar
Taketo Sano 2/5/2020 5:45 AM
たぶん分かりました、CPP の方は alive = 0 の vertex に対しても辺を(無駄に)生成してるっぽいです…😂
5:49 AM
恐らく BuildEdges に if(!Graph[MM][index]) continue; を挿入すると、辺の生成総数は一致すると思います(そして計算もより速く…) (edited)
Avatar
omochimetaru 2/5/2020 5:55 AM
今、もっと、決定的な差が、発見できました。
Avatar
Taketo Sano 2/5/2020 5:56 AM
Avatar
omochimetaru 2/5/2020 5:56 AM
しょうしょおまち
Avatar
Taketo Sano 2/5/2020 5:56 AM
ドキドキ💓
Avatar
omochimetaru 2/5/2020 6:07 AM
GitHub Gist: instantly share code, notes, and snippets.
6:07 AM
検索の実行回数が60倍違います。
6:07 AM
検索対象のサイズも10倍ぐらい違う。(ただこれはSetを使うことで影響を消せてるかも (edited)
6:12 AM
を挿入すると、辺の生成総数は一致すると思います(そして計算もより速く…)
これやってみました。 結果を、memo-3のコメント欄に追記しました。 かなり一致度が高くなりました!
6:13 AM
まだ1000本ぐらいC++のほうが多いけど7万というオーダーは揃った。
Avatar
Taketo Sano 2/5/2020 8:13 AM
遅くなりました、今から確認します。
Avatar
Taketo Sano 2/5/2020 8:26 AM
間違ったことを書きました🙇‍♂️
Avatar
Taketo Sano 2/5/2020 8:51 AM
まだ仮説に過ぎませんが,実は edges に順序がついてるのが本質的に効いてるのかもしれません.僕のコードでは x = source に対して,y = target をその targets の中の anyElement として選んでいますが,CPP の方は target = Graph[MM][source].out.front() と最初のものを選んでいます. 辺を取り除くたびに残った頂点たちから生える辺はより密になって行きますが,first から選ぶことで生えてる辺の個数が少ない頂点を選んでいるのかもしれません… もうちょっと考えてみます. (edited)
8:54 AM
その点以外は,使ってるデータ構造の違いしかなく,検索の総数に違いが出る理由はないように見えます…
9:00 AM
とりあえず言語の違いではなく,僕の実装がクソだというところに原因がありそうです…! (結果的に beginner だったということになりそう🙌
9:06 AM
@omochimetaru この計算は,11n37 に対するものですか?
Avatar
omochimetaru 2/5/2020 9:07 AM
はい、そうです > 11n37
9:09 AM
実験用のコードを共有しましょうか?
Avatar
Taketo Sano 2/5/2020 9:11 AM
大丈夫です,とりあえず searchCount で見て見ます!
9:14 AM
なんでこんな違いが出るのかサッパリ分からない🙌
Avatar
omochimetaru 2/5/2020 9:14 AM
ww
9:15 AM
なんか処理の進め方(yの選び方?)によって、後々の処理量が大きく変わるような
9:15 AM
そういう雰囲気があるけど
9:15 AM
僕はそもそものやってる事が全くわからないので全然イメージがつかない・・・ (edited)
Avatar
Taketo Sano 2/5/2020 9:17 AM
edge を Array にして first を取り出すようにしてみたところ,検索数が 300万 → 100万 ぐらいに減りましたが(それだけでも結構驚きですが),CPP の方は数万ですもんね…
9:17 AM
何かもっと本質的な無駄をしてしまってる気がする
9:17 AM
しかしそれがさっぱり分からない🙌
Avatar
omochimetaru 2/5/2020 9:17 AM
それと、C++ではMM=16から=23 の以外のケースでは searchCount = 0 がたくさんあるのも気になります。
9:18 AM
AlexanderDegreeで4つに分割できるって話だったんで、
9:18 AM
C++の方でも、あと3つはsearchCount=1が出てきそうな気がするんですけど。
Avatar
Taketo Sano 2/5/2020 9:19 AM
確かに
Avatar
omochimetaru 2/5/2020 9:19 AM
MM=23から16にかけての処理は、連鎖的に何か影響を与えて削減されているのだとしても、 23-16と他のAlexになってるグループはその影響をうけないと思うから、また同じ条件から始まるはずと言うか。 (edited)
Avatar
Taketo Sano 2/5/2020 9:20 AM
(23 - 16 + 1) = 8, (4 - (-5) + 1) = 10 の差は何かということですよね?
Avatar
omochimetaru 2/5/2020 9:21 AM
たしかに、そこも違うし
9:21 AM
@@@ loop=13, alex= 1, k= 4: searchCount= 5, size= 50, ave= 10, max= 12 allSearchCount= 3653463 @@@ loop=14, alex= 1, k= 3: searchCount= 258, size= 3364, ave= 13, max= 24 allSearchCount= 3653721 @@@ loop=15, alex= 1, k= 2: searchCount= 3075, size= 45772, ave= 14, max= 44 allSearchCount= 3656796 @@@ loop=16, alex= 1, k= 1: searchCount= 11211, size= 233691, ave= 20, max= 72 allSearchCount= 3668007 @@@ loop=17, alex= 1, k= 0: searchCount= 11653, size= 297422, ave= 25, max= 65 allSearchCount= 3679660 @@@ loop=18, alex= 1, k=-1: searchCount= 3974, size= 56627, ave= 14, max= 38 allSearchCount= 3683634 @@@ loop=19, alex= 1, k=-2: searchCount= 429, size= 2535, ave= 5, max= 13 allSearchCount= 3684063 @@@ loop=20, alex= 1, k=-3: searchCount= 10, size= 20, ave= 2, max= 2 allSearchCount= 3684073
9:22 AM
alex=1のk=4..-3の分のsearchCountはC++の方だと(MM=いくつのところだろう?)0しかないし。 (edited)
Avatar
Taketo Sano 2/5/2020 9:23 AM
とりあえずこれは僕の実装に問題がある話な気がするので,こちらのチャンネルからは撤退した方がいい気がしました.みなさん色々とアドバイスをくださりありがとうございます🙇‍♂️
9:23 AM
絶望のあまり「こういう処理は Swift でやらない方がいい」などと口走ってしまってすみません🙇‍♂️ まずは自分を疑わねばなりませんね😔 (edited)
Avatar
omochimetaru 2/5/2020 9:25 AM
そうですね、とりあえず、現状だと言語の差よりロジックの差が支配的なようです。 個人的にはひとまずそれが示せてよかった。
🙇‍♂️ 1
Avatar
辺が張られる最も簡単なケースが 5_1 で,すでに両者に違いが見られました: theirs: 14: (V, E) = (1, 0) 0 searches 13: (V, E) = (21, 77) 66 searches 12: (V, E) = (42, 88) 32 searches 11: (V, E) = (15, 45) 0 searches 10: (V, E) = (6, 12) 0 searches 9: (V, E) = (1, 1) 0 searches mine: 0 : (V, E) = (1, 0) 0 searches -1 : (V, E) = (21, 77) 79 searches -2 : (V, E) = (42, 88) 140 searches -3 : (V, E) = (15, 45) 82 searches -4 : (V, E) = (6, 12) 5 searches -5 : (V, E) = (1, 1) 0 searches (edited)
Avatar
omochimetaru 2/5/2020 12:36 PM
おお!しかも結構な差が出てる
Avatar
明らかにもっと早くこういう検証をしとくべきでしたね… アルゴリズムは間違ってないという思い上がりが…
Avatar
張られてる辺の数は一致してそうです.
Avatar
omochimetaru 2/5/2020 12:37 PM
5-1いいかたちだ
Avatar
👍
Avatar
Build Edges: 13 0 -> 34 0 -> 47 0 -> 0 0 -> 1 0 -> 2 0 -> 3 1 -> 48 1 -> 0 1 -> 4 1 -> 6 1 -> 5 2 -> 43 2 -> 27 2 -> 7 2 -> 8 2 -> 5 3 -> 49 3 -> 1 3 -> 4 3 -> 9 3 -> 10 4 -> 44 4 -> 28 4 -> 7 4 -> 11 こういう感じでデバッグしてきますw
12:53 PM
こうやるしかないw
Avatar
Taketo Sano 2/5/2020 1:58 PM
やはり頂点や辺に順序がついてることが本質的なようです…! (edited)
Avatar
Taketo Sano 2/5/2020 2:12 PM
x -> y を選択する際に, a -> y なる a が最も少ない y を選ぶようにしたら 10_152 の計算が完了しました…!
👏 1
2:13 PM
あっ
2:13 PM
すいません,これ @omochimetaru さんに DM 送ってるつもりが思いっきり #swift に投稿してました🤯
2:15 PM
アホ丸出しですいません🙇‍♂️
Avatar
omochimetaru 2/5/2020 2:28 PM
おお~
Avatar
omochimetaru 2/6/2020 6:50 AM
6:52 AM
@norio_nomura toolchainをdebug symbolと一緒に入れてsymbolic breakpointを貼って見るやつ、 確かにspecializeされたシンボルも含まれたけど、 おそらくstdlibに含まれるやつだけで、 アプリ側で作られたものはヒットしなかった。 $ss10_NativeSetV9insertNew_2at8isUniqueyxn_s10_HashTableV6BucketVSbtF11SwiftyKnots11GridComplexV9GeneratorV_Tg5 (generic specialization <SwiftyKnots.GridComplex.Generator> of Swift._NativeSet.insertNew(_: __owned A, at: Swift._HashTable.Bucket, isUnique: Swift.Bool) -> ()) などがヒットしてない
Avatar
omochimetaru 2/6/2020 7:07 AM
7:08 AM
そして、COWのコピーを発見した
7:09 AM
7:10 AM
ブレークしたいタイミングを制限するために、こんな方法を発見した↑
7:11 AM
あ〜、↑のcodomain.remove の内部でのコピーは、ループのホットスポットではないから問題ないかも。
Avatar
norio_nomura 2/6/2020 8:33 AM
アプリ側で作られたものはヒットしなかった
ほんとだ。
(edited)
8:35 AM
lldbでbreakpoint set -r NativeSet.insertNewとすると、アプリ側で作られたものにもヒットする。
8:37 AM
(lldb) breakpoint set -r Generator.*NativeSet.insertNew Breakpoint 15: 2 locations. (lldb) b Current breakpoints: 15: regex = 'Generator.*NativeSet.insertNew', locations = 2, resolved = 2, hit count = 0 15.1: where = SwiftyKnots-Sample`generic specialization <SwiftyKnots.GridComplex.Generator> of Swift._NativeSet.insertNew(_: __owned A, at: Swift._HashTable.Bucket, isUnique: Swift.Bool) -> () at <compiler-generated>, address = 0x0000000100009030, resolved, hit count = 0 15.2: where = SwiftyKnots-Sample`generic specialization <SwiftyKnots.GridComplex.Generator> of Swift._NativeSet.insertNew(_: __owned A, at: Swift._HashTable.Bucket, isUnique: Swift.Bool) -> () at <compiler-generated>, address = 0x00000001000bdf60, resolved, hit count = 0
8:39 AM
Xcode GUIのBreakpoint navigatorには表示されないけど。
Avatar
omochimetaru 2/7/2020 1:40 AM
-r <regular-expression> ( --func-regex <regular-expression> ) Set the breakpoint by function name, evaluating a regular-expression to find the function name(s).
1:44 AM
できた。
1:46 AM
うーん?XcodeのGUIのsymbolicってのはどのモードなんだろう
1:46 AM
help breakpoint set を見たけどよくわからなかった
Avatar
norio_nomura 2/7/2020 1:46 AM
たぶん-n -n <function-name> ( --name <function-name> ) Set the breakpoint by function name. Can be repeated multiple times to make one breakpoint for multiple names (edited)
Avatar
omochimetaru 2/7/2020 1:48 AM
ふむ。試してみたら同じ結果が出るな
Avatar
👀 https://github.com/apple/swift/pull/29775
This will be used for compiler-driven type erasure
This will be used for compiler-driven type erasure for dynamic replacement of functions with an opaque return type. For now, just parse the attribute and ignore it.
Avatar
omochimetaru 2/12/2020 7:36 AM
hborla@apple.com
7:37 AM
Appleじゃん
Avatar
これを宣言しておくと、existentialを作るとtype erasureになる、とかかしら。
Avatar
omochimetaru 2/12/2020 7:37 AM
class AnyP: P1 {} @_typeEraser(AnyP) // okay protocol P1 {}
7:37 AM
テストコードがちょっと謎、attributeテストだけだからかな。
Avatar
テストケースを見る限りは実装はユーザーサイドで…というように見えるんですよね。
Avatar
omochimetaru 2/12/2020 7:38 AM
P1 の erasure として AnyP を自動定義する んじゃない?
Avatar
struct AnySequence: Sequence { ... } @_typeErasure(AnySequence) protocol Sequence { ... } ってことか。
Avatar
omochimetaru 2/12/2020 7:39 AM
むむ・・・?
Avatar
これをやると、Sequence の
7:40 AM
Existential が作れるようになるが実体は AnySequence
Avatar
omochimetaru 2/12/2020 7:40 AM
erasureがprotocolに対して1つに定まっちゃうのがなんか変な感じ
Avatar
ってのが tarunon 予想ですよね?
Avatar
ですです
7:40 AM
アトリビュートの宣言位置から想像出来るのはそういう機能
Avatar
omochimetaru 2/12/2020 7:41 AM
This will be used for compiler-driven type erasure for dynamic replacement of functions with an opaque return type.
with ORT がよくわからん
Avatar
タイトルだけ見ると、erasureの実装を埋めるCodable的な機能を予想したんですが、テストケースは違うようだった。
Avatar
omochimetaru 2/12/2020 7:41 AM
ORTの抽象表現として使うって意味かしら??
7:41 AM
最初はORTのruntime representationを再利用してtype erasureを提供するって意味かと思ったんだけど逆かもしれない
7:42 AM
そうすると、ORT の generic ABI representation が AnySequence になるから
7:43 AM
既存のStdlibのAnySequenceを返してる関数が、 some Sequenceを返すAPI定義にアップグレードしつつも、 既存のAnySequenceを返す実装とABI互換性が保てる。
Avatar
omochimetaru 2/13/2020 1:48 AM
@omochi Yes, the spelling is intentional. The type eraser is the type that implements type erasure.
type erasureは型消去というパターンの事で、それを実現するための型消去器(とでも言えばいいのか)の事を type eraser と呼ぶらしい。
(edited)
Avatar
つまり、 AnySequence は type erasure ではなく type eraser ってことね。
Avatar
omochimetaru 2/13/2020 3:18 AM
そう。
Avatar
@swift-5.1.5 print(#file)
Avatar
<stdin>
Avatar
昔って #file でフルパスがとれてたような気がしたんですが気のせいですっけ?
Avatar
omochimetaru 2/15/2020 9:32 AM
つい最近かわりましたよ
9:32 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
そうだったのか。知りませんでした。ありがとう。
👍 1
9:37 AM
@swift-5.1.5 print(#filePath)
Avatar
exit status: 1 with stderr:<stdin>:1:7: error: use of unknown directive '#filePath' print(#filePath) ^
Avatar
これってもう実装されてて #filePath はまだ実装されてないってこと??
9:38 AM
というか、 5.1.3 時点ですでに絶対パスじゃなくなってるような・・・。
Avatar
omochimetaru 2/15/2020 9:53 AM
詳細な進捗は追ってなくてわからないです
Avatar
norio_nomura 2/16/2020 1:13 AM
まだレビュー中では。
Avatar
ステータスみるとそうなんですけど、実際実行してみたらすでに絶対パス返ってこなくないですか?僕のローカルは 5.1.3 です。
Avatar
norio_nomura 2/16/2020 9:38 AM
ソースファイルがカレントディレクトリにある場合はファイル名だけになるのですね、知りませんでした。 (edited)
Avatar
norio_nomura 2/16/2020 9:47 AM
あいや、正確にはコマンドラインでコンパイラへ渡されたパスが使われるのか。
Avatar
あそうだったのか、常に絶対パスに直されるものと思い込んでいた
Avatar
sh-session $ pushd (mktemp -d) $ echo 'print(#file)'>a.swift $ swift a.swift a.swift $ swift ./a.swift ./a.swift $ swift (pwd)/a.swift /var/folders/kt/2mwy9b_56_7993x190pl_1fh0000gn/T/tmp.3q2Yqu5G/a.swift
Avatar
Kishikawa Katsumi 2/17/2020 3:48 AM
guard let URL = URL(string: "\(baseURL)api/v0/tsdb/latest") else { fatalError() } ^ は書けるけど let URL = URL(string: "\(baseURL)api/v0/tsdb/latest")! ^ とは書けなかった。Variable used within its own initial value
Avatar
確かにoptional bindingはshadowingで特別な処理が挟まってそうですね
3:51 AM
let URL = Foundation.URL(string: "\(baseURL)api/v0/tsdb/latest")! これなら許されるはず (edited)
Avatar
omochimetaru 2/17/2020 3:52 AM
一貫性が無くて気持ち悪いですね。
Avatar
Kishikawa Katsumi 2/17/2020 4:03 AM
おお、右辺をFQNにする手があるのか
Avatar
Swift provides ergonomic interoperability with C (How Swift Imports C APIs), Objective-C (Importing Objective-C into Swift, Importing Swift into Objective-C), and Python ([1], [2], [3]). Interoperability between Swift and C++ has been previously discussed on the forums ([1], ...
👀 1
6:56 PM
かつてAppleでSwiftのstdlibの主要開発者であったDmitri。今はGoogleにいてしばらくclangdの開発をしていたのですが、最近はSwift C++ interoperability をやっているようです。まだ読めてないけど、Manifestとかすごい真面目にかいてる。
Avatar
Kishikawa Katsumi 2/17/2020 10:57 PM
半分まで読んだけどやはりめっちゃ考えることありますね。思ってたののさらに3倍くらいあるって感じだ。
Avatar
Kishikawa Katsumi 2/17/2020 11:25 PM
C++のNamespaceを空のSwift Enumにマッピングする(お、いけるんちゃう?)、でも細かいこと考えていくとハックが積み上がるからいっそC++を使うとき限定の言語機能を導入してもいいんじゃない?っていうところはそれでいいんだろうかという感じもするが、どうなんかな。
Avatar
omochimetaru 2/18/2020 3:25 AM
C++ manifesto今日読もうと思ってた 元々Appleに居たんですね
Avatar
omochimetaru 2/26/2020 2:49 AM
長かったけど軽く読んだ・・・
2:50 AM
参照型と右辺値参照型のマッピングは結構悩ましいですね
2:51 AM
テンプレートは基本的に事前特殊化を前提にいろんなバリエーションを検討してある感じだった。
2:53 AM
それでユースケース対応できるのかイマイチ想像しきれない
Avatar
↓これ記法混乱してない? void じゃなくて func では? // C++ header imported in Swift. void printInt(_ value: UnsafePointer<Int>) https://github.com/apple/swift/blob/4e12db450677d7c10b9dbfa9b1aa576385b9cd21/docs/CppInteroperabilityManifesto.md#const-reference-parameters
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 2/26/2020 3:16 AM
ww ほんとだ。
3:17 AM
俺も一個typo見つけたんだよな
Avatar
その直後のコードも混乱が。
Avatar
omochimetaru 2/26/2020 3:19 AM
インラインレビューってレビュワー指定されてないとできないんだっけ?
3:21 AM
スレッドに書き込んじゃった。
Avatar
どうだっけ?権限にもよるのかな?
Avatar
omochimetaru 2/26/2020 3:29 AM
void caller() { のミスが複数箇所あるからこっちの件はコメント欄だと伝え漏れが出そうですね。
Avatar
omochimetaru 2/26/2020 3:40 AM
PRのブランチに対するPRだ。
Avatar
norio_nomura 2/26/2020 3:43 AM
普通にdiffへコメント付けられない? https://github.com/apple/swift/pull/29880/files
Avatar
omochimetaru 2/26/2020 3:43 AM
あれ、ほんとだ。[+] ボタンありますね。
3:44 AM
さっき見ててわからなかったんだよな。
3:44 AM
あ、Rich Diff モードだとできないのか。 (edited)
3:44 AM
Source Diffモードだとボタンが出た。
3:45 AM
やり直した。
Avatar
あー、それだとわざわざ PR にせずコメントの方が良かったかな・・・。
11:44 PM
コードサンプルのシェルプロンプトが > なのが微妙に分かりづらいな😅
Avatar
これはもう別物だ
6:07 AM
multiple trailing closureのレビューが来た。優先度高いしSwiftUI圧を感じる。
Avatar
SwiftUI圧w
Avatar
omochimetaru 3/4/2020 6:08 AM
去年よくわからん機能が優先してゴリゴリ進められてるな〜と思ったらWWDCあけてみたら全部SwiftUI関連だったので
6:09 AM
SwiftUIの書き心地に関連する機能は優先度が高いと思っている
Avatar
はたして言語機能がDSLのために拡張されていくのは望まれる事なのかどうなのか...
6:09 AM
macroいれてそっちでやれと思わなくもない
Avatar
omochimetaru 3/4/2020 6:09 AM
一応一つ一つのdiscussionはSwiftUIと独立して価値が合意されてるんですけどね。
Avatar
けど、scalaの最近のmacro非互換みてるとうーんとも思う
Avatar
omochimetaru 3/4/2020 6:10 AM
macroは良くないと思う。
6:10 AM
自由度が高すぎてその上で難しいものが発展しすぎると
Avatar
バランスですよね。
Avatar
omochimetaru 3/4/2020 6:11 AM
後々ややこしくなっちゃう。
Avatar
ruby界隈でみてきた気がする(chef, puppet...)
Avatar
omochimetaru 3/4/2020 6:12 AM
古くはCのpreprocesssorもそうですね。 (edited)
Avatar
歴史は繰り返すってやつ
Avatar
omochimetaru 3/4/2020 6:13 AM
Swiftはその歴史を繰り返すまいと慎重みたいですよ。節々でそういう発言がなされる。
6:13 AM
SwiftUIで使ってるFunctionBuilderが地獄の釜じゃないのかどうかはちょっとわかんないけど・・・ 結構制限が強いのでギリギリセーフかなあと思ってる
Avatar
fbは結構際どいと思うw
Avatar
omochimetaru 3/4/2020 6:14 AM
際どいよね。
Avatar
Kishikawa Katsumi 3/4/2020 6:16 AM
FunctionBuildersはSwiftUI専用でしばらく進めるのがいいんじゃないかな。
Avatar
omochimetaru 3/4/2020 6:16 AM
Yay for code review. @pathofshrines noted a subtle omission in constraint generation that affected the semantics of switch statements in function builders. The fix was trivial but the implications are really interesting: https://t.co/NQTrOkdrSU:
6:16 AM
↑switch文対応が入ったよ。
Avatar
ウオオ
Avatar
Kishikawa Katsumi 3/4/2020 6:16 AM
Property Wrappersも便利だけどあれも強力すぎる気がする
Avatar
property wrapperとfunction builderの2つは
Avatar
omochimetaru 3/4/2020 6:17 AM
Property wrapperはちょっとドットアクセスが省略されてるだけっちゃだけ
Avatar
明確にそれまでのswiftとは毛色の違う機能だなと思っていて
Avatar
omochimetaru 3/4/2020 6:17 AM
それはそうだね〜 初見殺し度が高いよね。
6:17 AM
知らなきゃ全く意味不明で予想もつかない事が起きる。
6:18 AM
PWの$ 付けたアクセスとかやばいよね。
Avatar
$yあばい
6:18 AM
discordぇ...
Avatar
a, _a, $a だもんな〜w
Avatar
omochimetaru 3/4/2020 6:20 AM
↑のswitch文のサンプルコードとか見ると switch getSomeEnumOverloaded(17) { case .a: "a" default: "default" }
Avatar
Kishikawa Katsumi 3/4/2020 6:20 AM
いやあ@変数に代入したら何が起こるのか、っていうの標準ライブラリとCocoaだけならいいけど3rd Partyも入ると大変だなあと思う。
Avatar
あとinit(initialValue:)とinit(wrappedValue:)も
Avatar
omochimetaru 3/4/2020 6:20 AM
明らかにもう文指向じゃなくなってんだよな。 (edited)
Avatar
@PropertyWrapper@_functionBuilder 、型を定義する側のIDEのサポートも一切得られないので、結構渋い感じがする
Avatar
omochimetaru 3/4/2020 7:03 AM
IDEサポートは今後ついてくんじゃない?
7:04 AM
新規作成メニューからテンプレート生成とかでもいいし。
Avatar
まあそうか。機能を満たして無くてもコンパイル通ってしまうところに一抹の気持ち悪さを感じるんだよな
Avatar
omochimetaru 3/4/2020 7:05 AM
ああ確かに。
7:05 AM
間違ってても関係ないinitが生えてるだけになっちゃうのか。
7:06 AM
アノテーションでマーキングするのもそれ自体忘れたら同じだしなあ。 IDEが「init(initialValue:)の実装が無いですよ」みたいなのを薄く表示してくれるとかが良さそう。
Avatar
omochimetaru 3/4/2020 8:21 AM
0279スレ、結構反対意見あるな。
Avatar
omochimetaru 3/4/2020 8:29 AM
xwuさんの指摘してる丸括弧表記の場合とカンマ1文字しか違いが無いじゃんって指摘に同意だなあ
8:29 AM
かつ、もしカンマが嫌ならSE-0257を進めたらいいじゃん?、もそのとおりすぎる
8:33 AM
クリスラトナーが!
Strong -1.
Avatar
支配的な-1だ。。
Avatar
omochimetaru 3/4/2020 10:05 AM
ワイもコメントしてみた。Adrianさんが同じこと書いてたっぽいけど。
10:05 AM
UIView.animate { withDuration: 0.7 delay: 1.0 options: .curveEaseOut animations: animationFunction completion: completionFunction }
10:05 AM
↑これと何が違うの?と思って。
Avatar
(が{に変わっただけで嬉しくないやんけ!っていうのは何度かみた記憶がある
Avatar
omochimetaru 3/4/2020 10:07 AM
うん、それ複数回書かれてるんだけど
10:07 AM
末尾クロージャに限定しなくてもいい拡張になってると考えるとよりそれが強調されるなと思って。
Avatar
これ前スレに書こうとしてモニョくなって反芻してるんだが (edited)
Avatar
omochimetaru 3/4/2020 10:08 AM
どちらかというと「なぜか末尾クロージャに限定された」第二のカッコが追加される
10:08 AM
すごい不格好な話に見える。
Avatar
この言語拡張はラベル付きTrailingクロージャと、末尾以外Trailingクロージャの2回に分解した方が
10:08 AM
シュッと終わる気がしている
Avatar
omochimetaru 3/4/2020 10:10 AM
??
Avatar
つまり、複数のクロージャのTrailingを満たすための問題が2種類あって
Avatar
omochimetaru 3/4/2020 10:10 AM
「ラベル付きTrailingクロージャ」「末尾以外Trailingクロージャ」これ両方新概念か。
Avatar
その2種類は別々の話題として議論して、その2つの組み合わせで実現可能になる、という設計の方が
10:11 AM
筋良く議論出来て終わりそうだな、と。
Avatar
omochimetaru 3/4/2020 10:11 AM
それぞれ何の事〜
Avatar
2つに分けると、それぞれどちらも、なんでそれいるの?になりそうな気がするんですが。
Avatar
array.first { ... } を例えば array.first { where: ... } みたいに_で省略されてないラベルを見えるようにする、という話と (edited)
👀 1
10:13 AM
末尾以外の引数にクロージャを渡すときの糖衣を定義する、という話かな
10:13 AM
これ組み合わせると今の議論の置き換えになると思う
Avatar
omochimetaru 3/4/2020 10:14 AM
末尾以外を許可すると今の議論を超えた機能を提案することになるのでは。
Avatar
今の議論も最後から2番目とかのTrailingやろうとしてるわけで (edited)
Avatar
omochimetaru 3/4/2020 10:14 AM
あと、「末尾以外」だけ先に導入する事が不可能じゃない?
Avatar
本質的には同じだと思うけどね
Avatar
omochimetaru 3/4/2020 10:14 AM
あ、そこは前後順なのか
10:15 AM
たとえば↓これは0279では多分駄目 func f(a: () -> Void, b: Int) {} f(b: 0) { a: { () in } } (edited)
Avatar
それはそうだね
Avatar
言いたいことはなんとなく伝わってたんですが、改めてみると、「末尾以外Trailingクロージャ」というネーミングがじわじわくるw
Avatar
omochimetaru 3/4/2020 10:16 AM
末尾以外パラメータ(仮引数)のTrailingクロージャ実引数(argument)ってことね。 (edited)
Avatar
意味はわかるんですが、末尾じゃなければtrailingじゃないなと。名前だけで見て、ね。 (edited)
😆 2
Avatar
まあ結構難題だと思うんですけど、それをする上で、合理的な仕組みを作れば、2引数とかも普通に対応出来る結果になってるはず
10:18 AM
2引数をTrailing Closureにするという議論になっていることが、実態よりも簡単だと誤解される要因になっている気もする (edited)
10:18 AM
末尾じゃなければtrailingじゃない
それはそうw
Avatar
omochimetaru 3/4/2020 10:20 AM
結局最終的な形を考えないとあんまり良い着地にならないんじゃないか
10:20 AM
あと、「ラベル付きTrailingクロージャ」だけだと通る気がしない。
Avatar
個人的にはラベルが省略されるようになってしまった、というのは結構痛手な初期の設計ミスだと思っていて (edited)
10:21 AM
どうだろ、同意は得られないか
Avatar
omochimetaru 3/4/2020 10:23 AM
その気持ち悪さはわかる。
10:23 AM
呼び出しラベル省略できるかどうかは本来関数の定義側のラベル名で決まっているはずなのに
Avatar
ラベル付きを強制する(省略を不可にする)というものなら、まあ意味がある気がしますが、ラベル付きでも書けるというものなら、Trailingクロージャにしなくていいんじゃないと個人的には思います。
Avatar
omochimetaru 3/4/2020 10:24 AM
末尾仮引数の関数型だけは、呼び出し側で勝手にラベルを削除できてしまう。
Avatar
なので、これをどっちに倒したいか (ラベル付きTrailingを追加するか、いっそTrailingを禁止するか)という議題がまずはじめにあって
Avatar
omochimetaru 3/4/2020 10:24 AM
でも、現状仕様を残したまま、指定できる記法を入れる意味はないと思う。それは丸括弧で書けばいいから。
Avatar
後者に倒れるならそもそも複数引数のTrailingは不要だった。というわけです。
Avatar
omochimetaru 3/4/2020 10:26 AM
その観点でありえるのは「ラベル消しTrailingClosureを禁止する」だと思うけど下位互換破壊だから無理そう
Avatar
この辺をすっ飛ばして複数Trailing議論してるので、そりゃこじれるよなというのが
10:27 AM
ワイの感想であった
Avatar
omochimetaru 3/4/2020 10:27 AM
いずれにしても最終形は、proposalのalternative consideredに載ってるもの含めて、他に無いと思う。
10:27 AM
trailing closureっていう言語機能が嬉しいのって
10:28 AM
}) って閉じカッコが2重になるのを防げる事だと思っていて
10:28 AM
それが  }} になっても意味ないと思うんだよな。
10:29 AM
when(2 < 3) { 3 } else { 4 } ↑で、こういうぶら下げスタイルはparser的に厳しいとなるともう選択肢が無いと思う。
10:29 AM
(専用の変な記号でぶら下げる手はある)
10:30 AM
そうした意見は、話の進め方を変えたところで最終型の文法に対して有効な反論になるから、変わらない気がする。
Avatar
「ラベル消しTrailingClosureを禁止する」だと思うけど下位互換破壊だから無理そう
現実的にシンプルで良さそうだけど、やっぱ破壊的すぎて今からだとダメそうという同じ結論に至った・・・
😩 1
😢 1
Avatar
omochimetaru 3/5/2020 1:23 AM
UIView.animate(withDuration: 0.7) { animations: frame.size.width += 10 completion: _ in backgroundColor = .yellow }
1:23 AM
これはアリだな・・・・・・
1:25 AM
あーでも文法的にラベルに見えてしまうか
Avatar
「ラベル消しTrailingClosureを禁止する」だと思うけど下位互換破壊だから無理そう
@noomit label: () -> Void のようなアノテーションを導入したら下位互換は解決できそう?
Avatar
omochimetaru 3/5/2020 4:03 AM
たしかに。
Avatar
下位互換破壊って一年くらい前まではカジュアルにあったと思うんだけど
6:02 PM
もうやめることになったんだっけ。
Avatar
omochimetaru 3/6/2020 2:00 AM
Swift4が出たときにこれからはコード下位互換は壊さないようにしようねって雰囲気だったと思う
Avatar
↓このAPIに UnsafeMutablePointer<ObjCBool>? が使われてるのってなんででしょう? inout Bool? じゃダメ? NSFileManager のままなのかと思ったけど、 FileManager 導入時に気付けたような。 https://developer.apple.com/documentation/foundation/filemanager/1410277-fileexists
Avatar
omochimetaru 3/11/2020 4:55 AM
その話最近dorgがツイッターでしてましたね。 理由としてはObjctive-CのBOOLのポインタを機械的に変換したからで
4:55 AM
専用のオーバレイを用意するのが望ましいけどやりそこねた。
Avatar
やりそこねた・・・😂
Avatar
omochimetaru 3/11/2020 4:56 AM
Thank God Swift Foundation is fundamentally cross-platform 🤦‍♀️ We have even "ObjCBool" for non-objc platforms. https://t.co/5LMI66FXZY
4:57 AM
↑英会話むずいけど多分そんな話だと思う。 (edited)
4:58 AM
多分やるんだったらSwift3の時のAPI Swift化の時でしたね。
4:58 AM
Swift2のときは機械変換がいっぱいあった。 俺それ気がついてたし伝えたら良かったなあ。
Avatar
もしかして Foundation 捨てることも視野に入ってる? https://twitter.com/dgregor79/status/1234527858317389826
@krzyzanowskim @simjp Personally, I think we as a community should be focusing on great cross-platform Swift APIs and not continue to tune the import of Objective-C APIs. The latter is source-breaking and is at best good, but almost never great.
4:59 AM
swift-file とかできてほしい。
Avatar
omochimetaru 3/11/2020 4:59 AM
たしかに。
5:00 AM
この前もCryptoとかArgumentParserとか出してたし
5:00 AM
ちょこちょこ小さい単位で出していく気持ちもあるのかな。
Avatar
Kishikawa Katsumi 3/11/2020 5:01 AM
SPMのTSCにファイル操作のやつあるし、独立する可能性はあるんじゃない?
Avatar
omochimetaru 3/11/2020 5:01 AM
たしかに。
Avatar
swift- 系のライブラリは、今は SwiftPM 経由だけど、将来的にコンパイラに同梱配布も見込まれてるのかな?
Avatar
Kishikawa Katsumi 3/11/2020 5:02 AM
SwiftはPythonみたいにバッテリーインクルードの方針じゃなかったでしたっけ?
5:02 AM
^ (うろ覚え。)
Avatar
omochimetaru 3/11/2020 5:03 AM
どっちかというとSwiftPMでいろいろ必要なものを取ってくる方向に進んでるように感じます。
Avatar
そう、うろ覚えでそんな話を @omochimetaru がしていたような。 < バッテリーインクルード (edited)
Avatar
omochimetaru 3/11/2020 5:03 AM
あ〜でもStandardLibrary Previewは
5:03 AM
通ったものは入れてくからStandardLibraryは育つのかな。
Avatar
Kishikawa Katsumi 3/11/2020 5:04 AM
なるほど。じゃあ同梱はしないで本体はスリムのまま、かなあ。
Avatar
swift- 系は標準ライブラリじゃないからなぁ。
Avatar
omochimetaru 3/11/2020 5:04 AM
現時点でswift-系を分けててstandard library evolutionの流れにはしてないし、
5:05 AM
機能系(?)はSwiftPMで取る感じになっていきそう。
Avatar
標準ライブラリと分離しながらも、同梱されてて SwiftPM 通さずに import できたら便利そうな気が。やっぱりいちいち SwiftPM 通さないといけないのは不便な感じが。ファイル周りとか、ネットワーク周りとかも swift- に切り出すなら余計に。
Avatar
Kishikawa Katsumi 3/11/2020 5:05 AM
まあファイルIOは同梱してほしいけど負債になりやすいやつだから悩ましいですねえ。やはりケースバイケースか。
Avatar
omochimetaru 3/11/2020 5:06 AM
不便な感じ
それは、Package.swiftとかのことですか?
Avatar
うん
Avatar
omochimetaru 3/11/2020 5:07 AM
Script modeを強化して、swift-shみたいに、 単一ファイルでもimport文にリモートリポジトリパッケージを使えるようにしようっていう 方向性の話があるので、それで解決するのが良いと思ってます。
Avatar
Kishikawa Katsumi 3/11/2020 5:07 AM
Goっぽい。悪くないと思う。
5:08 AM
↑ここかな? Swift6 アナウンスのときにスレがちょっと復活した。
5:09 AM
クリスラトナーも2/3に > I love this pitch って書き込んでる。 (edited)
Avatar
うん、でもこれにしても、やっぱ import Foundation とだけ書けたのと比べると面倒だと思うんだよなぁ。
Avatar
omochimetaru 3/11/2020 5:10 AM
swift-shなら import Foundation import PromiseKit // @mxcl ~> 6.5 (edited)
Avatar
ファイルI/Oの度に↓を書きたいかどうか。 @package(url: "https://github.com/apple/swift-file.git", from: "1.0.0") import File (edited)
Avatar
Kishikawa Katsumi 3/11/2020 5:10 AM
ちょうどいいバランスになるんじゃないですか?
5:10 AM
必要とされるものは本体に同梱、そうでないものは@package importって感じで。
Avatar
omochimetaru 3/11/2020 5:11 AM
GithubのURL全部書くのはめんどくさいから、 GitHubだったら省略して、 import mxcl.PromiseKit とか書けると良いと思う。
Avatar
Kishikawa Katsumi 3/11/2020 5:11 AM
この辺の仕組みだと後から本体に同梱するようにした、とかも問題ないし。
Avatar
omochimetaru 3/11/2020 5:11 AM
中央リポジトリみたいなものがあればmxcl. も削れそう。
Avatar
GitHub だったら省略はどうだろう?外部サービスに言語仕様が依存するのは・・・
5:12 AM
中央リポジトリはいいかもだけど、 SwiftPM の中央リポジトリがない良さが。悩ましい・・・。
Avatar
omochimetaru 3/11/2020 5:12 AM
「標準でコンパイラと一緒に出荷するものを選ぶ」のと「中央リポジトリを用意する」って同じ話じゃないですか?
5:12 AM
GitHub特別扱いは外部サービスだからちょっと違うけど。
Avatar
中央リポジトリに登録するのが swift- だけならいいけどね。
Avatar
Kishikawa Katsumi 3/11/2020 5:13 AM
まあ import "github.com/kishikawakatsumi/KeychainAccess" でいいんじゃない。 Goと一緒。加えてSwiftはバージョンの指定ができる。
Avatar
サードパーティのライブラリも登録し始めると、 GitHub に push するだけって現状と比べると面倒になるなと。
5:14 AM
import "github.com/kishikawakatsumi/KeychainAccess" は、パッケージとモジュールが別だから一手間要りそうですね。
5:16 AM
パッケージ中の全モジュール import 扱いとかもできるかもですが、コード中にモジュール名が現れないのは、 Module.Foo とかするときに対応が分かりづらいのが・・・。
Avatar
omochimetaru 3/11/2020 5:16 AM
import KeychainAccess と同じ意味を想定しているのでは?
Avatar
Kishikawa Katsumi 3/11/2020 5:17 AM
import "github.com/swift/SourceKit-LSP/Core" import "github.com/swift/SourceKit-LSP/JSONRPC" Pathのように書けるとか
5:17 AM
^ これは妄想
Avatar
↑だとありだと思います。最後は / じゃなくて : とかの方が明確かもですが。
Avatar
Kishikawa Katsumi 3/11/2020 5:19 AM
まあ、中央リポジトリにしても書く方の複雑さはそれほど変わらないと思います。 CocoaPodsとかRubyGemでわかったように、名前空間がある程度必要なので、結局ドメイン的な衝突しないものが必要になる、のでそこそこ長くなるかと。
5:20 AM
そうすると、中途半端にこの場合は書けるってしてもたぶん覚えにくいだけとなりそうだからある程度カッチリ書く、っていうのは悪くないんじゃないかな。
Avatar
@omochimetaru リポジトリから指定したいモジュールが一意に定まらないので。たとえば import "github.com/apple/swift-numerics" として、 import Numerics なのか import ComplexModule なのか。
Avatar
omochimetaru 3/11/2020 5:21 AM
リポジトリ名とパッケージ名が別名の時は指定するとして、同名だったら省略が良いと思う。 (edited)
Avatar
Apple はリポジトリ名とパッケージ名を同名にすることは推奨してなさそうだし、パッケージ名と同名モジュール読み込みはできるけど、その場合はモジュール名が import 文に現れないのが気持ち悪い・・・。
5:23 AM
名前空間がある程度必要なので、結局ドメイン的な衝突しないものが必要になる、のでそこそこ長くなるかと。
そうですね。その上で swift- 系だけは特別扱いされるといいなと。 import File と書きたいです。
5:24 AM
話は逸れますが、今ってモジュール名が衝突した場合って解決できるんですっけ?
5:25 AM
import "github.com/swift/SourceKit-LSP/Core" みたいなのを想定すると、解決できてほしいですし、それが解決できるなら同じライブラリのバージョン違いを同時に使うとかもできそうですね。
Avatar
Kishikawa Katsumi 3/11/2020 5:26 AM
推奨してないことはないと思うんですよね。(どっちを推奨してるかは分からないけど)Appleが公開リポジトリに上げるようなものはそこそこの規模だから必然的にいろんなモジュールがかかわらざるをえない、んじゃないかな。
Avatar
swift- プレフィックスが付いてるのと、 GitHub の標準的なリポジトリ命名規則に従って小文字ハイフン区切りになっている辺りですね。
Avatar
Kishikawa Katsumi 3/11/2020 5:27 AM
モジュールの衝突は回避できないんじゃないかなあ。
Avatar
昔のサードパーティの Swift ライブラリのリポジトリって UpperCamelCase が多かったですけど、僕は最近は Apple の習って foo-bar-baz みたいにするようにしてます。
Avatar
Kishikawa Katsumi 3/11/2020 5:28 AM
import "github.com/swift/SourceKit-LSP/Core" ^ これはうろ覚えで import "github.com/swift/SourceKit-LSP/SKCore" こうでした。
Avatar
モジュール名衝突が回避できないと、
名前空間がある程度必要なので、結局ドメイン的な衝突しないものが必要になる、のでそこそこ長くなるかと。
の対応も中途半端になるかなぁと。
Avatar
Kishikawa Katsumi 3/11/2020 5:29 AM
swift- プレフィックスが付いてるのと、 GitHub の標準的なリポジトリ命名規則に従って小文字ハイフン区切りになっている辺りですね。
なるほど、確かに。
5:29 AM
モジュール名衝突はなんとかしてほしいですね。。。
Avatar
Java の FQDN で指定する方法みたいなのは必要だと思うんですよね。 (edited)
Avatar
Kishikawa Katsumi 3/11/2020 5:30 AM
Javaはそれとディレクトリ構造を一致させてしまったことがよくなかったですね😅
Avatar
そうですねw
5:32 AM
import "github.com/foo/bar:Module" as BarModule
5:32 AM
みたいなのがいいのかな。
Avatar
Kishikawa Katsumi 3/11/2020 5:33 AM
import時に別名をつける、というのは古いProposalがあったような気がしますね。
Avatar
omochimetaru 3/11/2020 5:33 AM
SKCore・・・ TSCもあるしなんかObjectiveCみたいになってきちゃってるよな。
Avatar
構文だけの問題じゃなくて、 ABI 安定化された今、そこの衝突回避ってできるんでしょうか?
Avatar
omochimetaru 3/11/2020 5:34 AM
SK prefix は SpriteKiteとかぶっちゃってるしな。
Avatar
Kishikawa Katsumi 3/11/2020 5:37 AM
追加仕様だったらいいんじゃない?
5:37 AM
ABIも今のところ限定的な話だし、壊すときは壊す気もする(別にいいと思う)。
Avatar
omochimetaru 3/11/2020 5:40 AM
現状だとパッケージ名がシンボルにマングルされてるから
5:40 AM
たとえソースコード側でパッケージ名に別名を付けてimportできたとしても、 元々のパッケージ名が同じだったら衝突しちゃうので一緒に使えないですね。
Avatar
import "github.com/foo/bar:Module" みたいなときはパス込みでシンボル名を作れば ABI 仕様を破壊しない?でも、既存の SwiftPM と衝突するかな。
Avatar
omochimetaru 3/11/2020 5:43 AM
パス形式でimportしたときはパスを埋め込んだシンボルにすれば、それは追加仕様なので下位互換は壊れないですね
5:44 AM
でも事前ビルドしたバイナリを配布する形式を考えると、
5:44 AM
利用側がどういうパスで指定したかとは関係なく
Avatar
それだと Package.swift に書かれたときは衝突回避できないから、 Package.swift もパス込みにした方がいい気が。
Avatar
omochimetaru 3/11/2020 5:44 AM
ライブラリ自体がユニークな名前を持っている必要がありそう。
Avatar
あと、これができれば同一ライブラリを別リポジトリに置いて重複importできるので、それだったらバージョン違いで重複importできてもいい気がする。
5:44 AM
なので、シンボル名にバージョンまで焼き込まれる。
Avatar
omochimetaru 3/11/2020 5:46 AM
それやると
5:46 AM
互換性のあるバージョン間で
5:46 AM
バイナリ差し替えができなそう。
Avatar
Kishikawa Katsumi 3/11/2020 5:47 AM
少なくとも、 1. コンパイル時にどっちのインターフェースを参照するか、はABI関係ないから記法とか順序とかで解決できる。
5:49 AM
でバイナリがどっちを呼ぶか、というのは、、、 とここまで書いてやっぱり難しいなと思いました。
5:49 AM
フレームワークとかモジュールの単位でFQDNみたいな区別できるものがないとだめじゃないですかね。
5:49 AM
つまり、今のSwiftが想定している名前空間では足りない。拡張する必要がある。 (edited)
Avatar
互換性のあるバージョン間でバイナリ差し替えができなそう。
なるほど。それは言い換えると、今は Package.swift に書くリポジトリ変わってもモジュール名同じなら互換性持たせられるけど、パスを焼き込んじゃったらそれもできなくなる?
Avatar
omochimetaru 3/11/2020 5:50 AM
同じパスのままバージョンが変わるかぎりは差し替えられる。
Avatar
うん。でも、リポジトリ引っ越しましたには対応できなくなっちゃうと。
Avatar
omochimetaru 3/11/2020 5:51 AM
そですね。 まあ、引越し先でも以前のパスを焼き込み続ければいけます。
Avatar
それは、実際のリポジトリの在り処と焼きこまれてるパスを独立に管理しないといけなくて大変そう・・・。 (edited)
Avatar
omochimetaru 3/11/2020 5:52 AM
まあそうですね。結局の所「焼きこまれてるパス」に相当するのが 岸川さんの書いてる「フレームワークとかモジュールの単位でFQDNみたいな区別できるもの」ですね。
Avatar
うーん、一意性を保証する一番お手軽な手段はリポジトリの在り処だと思うから、引っ越し時は諦めてリビルドくらいが現実的そう。
Avatar
Kishikawa Katsumi 3/11/2020 6:03 AM
区別する手段はリポジトリのURLでいいと思いますが、結局配布することを考えると、それがバイナリについてこないとダメなので名前空間の仕様は拡張しないと難しそうですよね。
Avatar
omochimetaru 3/11/2020 6:03 AM
URLだと文字列として長すぎて、シンボル全部に含まれるとなると、バイナリサイズがちょっと膨らみそうなのが気になるな。
Avatar
Kishikawa Katsumi 3/11/2020 6:06 AM
ビットを最大限使ってエンコーディングしたらいいのかな。 Swiftはモジュール名はHuman Readableな形で残ってるんでしたっけ?
Avatar
omochimetaru 3/11/2020 6:07 AM
概ねHumanReadableですね 同じ単語が2回出てくる時は参照記号に圧縮される。
🙏🏻 1
6:08 AM
http:// とか github.com を表す特別な記号とかを用意すれば少し圧縮することはできるかも?w
Avatar
Kishikawa Katsumi 3/11/2020 6:10 AM
考えてたら大変すぎてPrefixでも別にいいけど、って気分になってきた。
6:10 AM
まあまあちょうどいいバランスな気がする。
Avatar
omochimetaru 3/11/2020 6:11 AM
サブパッケージの機能は欲しいな。
6:11 AM
TSCBasic よりも SwiftToolsSupport.Basic になってて欲しい。
6:11 AM
使う側で as TSCBasic する事はあるかもしれないけど。
6:12 AM
SwiftPMでライブラリ作る時全部のパッケージにそのライブラリを現すprefixを付けるのはめんどくさい。
6:13 AM
URLやドメインを使わずにライブラリ名同士の衝突を防ぐためには中央リポジトリで名前登録する仕組みが必要だけどそれは悩ましいところだ。
6:14 AM
例えば FileKit みたいな名前ってファイル操作のライブラリを作ろう、って思ったら思いつきやすくて
6:14 AM
中央がある場合、最初に FileKit を取った人のものになっちゃうけど
6:14 AM
中央リポジトリがない場合、別の人の作った FileKit のほうが出来が良かったときに
6:15 AM
民主的に乗っ取れる可能性があるのは良いところな気もする。
6:15 AM
てか昔 antitypical じゃない Result もなかったでしたっけ
6:15 AM
まあ派閥が分裂した時はオシマイだけど・・・
Avatar
Kishikawa Katsumi 3/11/2020 6:20 AM
厳密にはFileKitとFileKitの衝突の話とさっきまでの話は別といえば別なんですよね。 FileKitとFileKit
6:21 AM
の衝突はResultもですが、両方を使いわけたいケースではないと思うので。
Avatar
omochimetaru 3/11/2020 6:21 AM
あ〜そうか。両方使いたい話と、どっちかが代表を取れる話は別ですね。
Avatar
Kishikawa Katsumi 3/11/2020 6:21 AM
いい感じの名前が取り合いになる問題はもう少しシンプルに解決できそうな気がしている。
6:22 AM
ただPackage.swift (import ~~)にフルパスが書ければいい?のかな。
6:23 AM
そこはたぶんそれでいい気がする。
Avatar
omochimetaru 3/11/2020 6:23 AM
フルパスが要らない短い記法は欲しいなあ・・・
👍 1
6:25 AM
今ってコマンドラインツールだととりあえずimport Foundation すればよいところがあるけど
6:25 AM
これからさきだんだん、ファイル操作ならXX、通信ならYY、みたいなのを覚えていく事になりそうで。
Avatar
TestFlightでの稼働か、AppStore経由での正式リリースかを判定する方法ってないですかね。(#if DEBUG的な感じでできるとととてもありがたいんだけどw)
Avatar
if Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt" { ~ }
Avatar
omochimetaru 3/19/2020 5:26 AM
protocol Cat { func play(catToy: Toy) } let fn = Cat.play fn(myCat)(myToy) プロトコルメソッドを一級オブジェクトとして取れるようになったらしい。 https://github.com/apple/swift/pull/28698/files
Avatar
ほおー
Avatar
omochimetaru 3/19/2020 5:28 AM
これ、従来は呼び出しだけでもジェネリック関数を経由しないといけなかったし、 いったん関数の形にするのは今までは無理だったんじゃないかな? 多分継承boxでeraseしないといかん
Avatar
omochimetaru 3/19/2020 5:30 AM
レシーバと引数で2階のカリー化されてるのはstructのメソッドとかと同じですね。
Avatar
omochimetaru 3/19/2020 5:49 AM
あーこれ <T: P>(T) -> (A) -> R じゃなくて (P) -> (A) -> R かも。。?
Avatar
Kishikawa Katsumi 3/24/2020 7:06 AM
@swiftbot import Foundation struct DocumentSymbol: Encodable {} class Service { func perform() { sendDocumentSymbolRequest(context: [:], resource: "", slug: "", path: "") { (_, _) in } } private func sendDocumentSymbolRequest(context: [String : String], resource: String, slug: String, path: String, reply: @escaping (Bool, [String : Any]) -> Void) { let documentSymbols = [DocumentSymbol()] reply(true, ["result": "success", "value": encodeResponse(documentSymbols)]) } private func encodeResponse(_ documentSymbol: DocumentSymbol) -> [String: Any] { print("A") return [:] } private func encodeResponse(_ documentSymbols: [DocumentSymbol]) -> [String: Any] { print("B") return [:] } private func encodeResponse<T: Encodable>(_ response: T) -> Any { print("C") let data = try! JSONEncoder().encode(response) return try! JSONSerialization.jsonObject(with: data, options: []) } } let service = Service() service.perform()
Avatar
swiftbot BOT 3/24/2020 7:06 AM
Author icon
kishikawakatsumi
import Foundation struct DocumentSymbol: Encodable {} class Service { func perform() { sendDocumentSymbolRequest(context: [:], resource: "", slug: "", path: "") { (_, _) in } } private func sendDocumentSymbolRequest(context: [String : String], resource: String, slug: String, path: String, reply: @escaping (Bool, [String : Any]) -> Void) { let documentSymbols = [DocumentSymbol()] reply(true, ["result": "success", "value": encodeResponse(documentSymbols)]) } private func encodeResponse(_ documentSymbol: DocumentSymbol) -> [String: Any] { print("A") return [:] } private func encodeResponse(_ documentSymbols: [DocumentSymbol]) -> [String: Any] { print("B") return [:] } private func encodeResponse<T: Encodable>(_ response: T) -> Any { print("C") let data = try! JSONEncoder().encode(response) return try! JSONSerialization.jsonObject(with: data, options: []) } } let service = Service() service.perform()
Version:
swift-5.1.3-RELEASE
Output:
B
Error:
Avatar
Kishikawa Katsumi 3/24/2020 7:06 AM
^ これは当然Bが呼ばれるのだけど、
7:07 AM
AとBのメソッドにデフォルト引数を足すと(デフォルト引数なのでCall siteの変更はナシ)
7:07 AM
@swiftbot import Foundation struct DocumentSymbol: Encodable {} class Service { func perform() { sendDocumentSymbolRequest(context: [:], resource: "", slug: "", path: "") { (_, _) in } } private func sendDocumentSymbolRequest(context: [String : String], resource: String, slug: String, path: String, reply: @escaping (Bool, [String : Any]) -> Void) { let documentSymbols = [DocumentSymbol()] reply(true, ["result": "success", "value": encodeResponse(documentSymbols)]) } private func encodeResponse(_ documentSymbol: DocumentSymbol, _ indent: Int = 0) -> [String: Any] { print("A") return [:] } private func encodeResponse(_ documentSymbols: [DocumentSymbol], _ indent: Int = 0) -> [String: Any] { print("B") return [:] } private func encodeResponse<T: Encodable>(_ response: T) -> Any { print("C") let data = try! JSONEncoder().encode(response) return try! JSONSerialization.jsonObject(with: data, options: []) } } let service = Service() service.perform()
Avatar
swiftbot BOT 3/24/2020 7:07 AM
Author icon
kishikawakatsumi
import Foundation struct DocumentSymbol: Encodable {} class Service { func perform() { sendDocumentSymbolRequest(context: [:], resource: "", slug: "", path: "") { (_, _) in } } private func sendDocumentSymbolRequest(context: [String : String], resource: String, slug: String, path: String, reply: @escaping (Bool, [String : Any]) -> Void) { let documentSymbols = [DocumentSymbol()] reply(true, ["result": "success", "value": encodeResponse(documentSymbols)]) } private func encodeResponse(_ documentSymbol: DocumentSymbol, _ indent: Int = 0) -> [String: Any] { print("A") return [:] } private func encodeResponse(_ documentSymbols: [DocumentSymbol], _ indent: Int = 0) -> [String: Any] { print("B") return [:] } private func encodeResponse<T: Encodable>(_ response: T) -> Any { print("C") let data = try! JSONEncoder().encode(response) return try! JSONSerialization.jsonObject(with: data, options: []) } } let service = Service() service.perform()
Version:
swift-5.1.3-RELEASE
Output:
C
Error:
Avatar
Kishikawa Katsumi 3/24/2020 7:08 AM
Cが呼ばれるって変じゃないかな?
7:09 AM
互換性を保つように変更したつもりなのに呼ばれるメソッドが変わっているという罠。
7:10 AM
ちなみに、これは同じシグネチャでトップレベルのFunctionだと、どっちのケースもBが呼ばれる。インスタンスメソッドにするとこうなった。
Avatar
これはどのケースでもCが呼ばれるのが正しいと思います。
8:50 AM
Bは [String: Any] からAnyへの変換でペナルティを食らうけどCはペナルティなしじゃないですかね?
8:52 AM
インスタンスメソッドとトップレベル関数でオーバーロードの解決が違うのはよくわからない… (edited)
Avatar
omochimetaru 3/24/2020 8:52 AM
リテラルの型推論が組み合わさってるからこれ難しいな。
8:53 AM
とりあえず、デフォルト引数を追加しただけでオーバーロード選択結果が変わるのは変だと思います。
Avatar
@swiftbot -Xfrontend -debug-constraints protocol P {} struct S: P {} struct V { static let value = V() } class Service { func perform() { let s = S() let _: Any = encodeResponse(s) } private func encodeResponse(_ s: S, indent: V = V.value) -> [String: Any] { fatalError() } private func encodeResponse<T: P>(_ response: T) -> Any { fatalError() } } let s = Service() s.perform() (edited)
Avatar
swiftbot BOT 3/24/2020 8:55 AM
(edited)
Author icon
kateinoigakukun
protocol P {} struct S: P {} struct V { static let value = V() } class Service { func perform() { let s = S() let _: Any = encodeResponse(s) } private func encodeResponse(_ s: S, indent: V = V.value) -> [String: Any] { fatalError() } private func encodeResponse<T: P>(_ response: T) -> Any { fatalError() } } let s = Service() s.perform()
Version:
swift-5.1.3-RELEASE
Output:
Error:
Fatal error: file /usercode/main.swift, line 19 Current stack trace: 0 libswiftCore.so 0x00007f1672a4f3a0 swift_reportError + 50 1 libswiftCore.so 0x00007f1672ac0090 _swift_stdlib_reportFatalErrorInFile + 115 2 libswiftCore.so 0x00007f16729e44fe <unavailable> + 3515646 3 libswiftCore.so 0x00007f16729e4677 <unavailable> + 3516023 4 libswiftCore.so 0x00007f16727d9ddd <unavailable> + 1375709 5 libswiftCore.so 0x00007f16729bb458 <unavailable> + 3347544 6 libswiftCore.so 0x00007f16727d9179 <unavailable> + 1372537 10 swift 0x00000000005283fe <unavailable> + 1213438 11 swift 0x000000000052cce2 <unavailable> + 1232098 12 swift 0x000000000051cdbf <unavailable> + 1166783 13 swift 0x000000000050b5e8 <unavailable> + 1095144 ...
8:55 AM
Avatar
omochimetaru 3/24/2020 8:55 AM
おや。
8:55 AM
ああfatalError入れてるのか
Avatar
あれオプション間違ってます?
Avatar
omochimetaru 3/24/2020 8:57 AM
@swift-main -frontend -typecheck -debug-constraints protocol P {} struct S: P {} struct V { static let value = V() } class Service { func perform() { let s = S() let _: Any = encodeResponse(s) } private func encodeResponse(_ s: S, indent: V = V.value) -> [String: Any] { [:] } private func encodeResponse<T: P>(_ response: T) -> Any { 0 } } let s = Service() s.perform()
8:57 AM
あれ?BOTちゃんが居ない。
8:57 AM
@swiftbot -frontend -typecheck -debug-constraints protocol P {} struct S: P {} struct V { static let value = V() } class Service { func perform() { let s = S() let _: Any = encodeResponse(s) } private func encodeResponse(_ s: S, indent: V = V.value) -> [String: Any] { [:] } private func encodeResponse<T: P>(_ response: T) -> Any { 0 } } let s = Service() s.perform()
Avatar
swiftbot BOT 3/24/2020 8:57 AM
Author icon
omochimetaru
protocol P {} struct S: P {} struct V { static let value = V() } class Service { func perform() { let s = S() let _: Any = encodeResponse(s) } private func encodeResponse(_ s: S, indent: V = V.value) -> [String: Any] { [:] } private func encodeResponse<T: P>(_ response: T) -> Any { 0 } } let s = Service() s.perform()
Version:
swift-5.1.3-RELEASE
Output:
Error:
Avatar
型変数の置き方が全然違いますね
Avatar
Kishikawa Katsumi 3/26/2020 11:28 AM
まだよくわかってないのだけれど、 final class CreatorThumbnailImageView: UIView { @Published var images = [PlayLogUploadParameter]() { didSet { ... } } ... } ^ のようなクラスがあるとして、 thumbnailImageView.images.append(image) のような操作をしたときにDidSetが呼ばれない現象がXcode 11.4で発生している。 Xcode 11.3.1でビルドして実行するとDidSetが呼ばれる。
Avatar
Hi all, Something I noticed in Swift 5.2 in the latest betas, and the latest snapshots, when you use a property wrapper for a struct, and you set a value inside the struct, a didSet does not get called. For example: import Combine struct MyStruct { var details: String }...
1:41 PM
この件ですかね🤔
Avatar
Kishikawa Katsumi 3/26/2020 1:46 PM
同じ事象のようですね。 Swift 5.2のバグ、なんですね。
Avatar
Kishikawa Katsumi 3/26/2020 1:55 PM
いや、違うな。私のは再代入するように変えたら動く、わけなので。
1:55 PM
iPhoneで見てるから細かいとこ読めてなかった。 (edited)
Avatar
nil as String? is AnyObject を Xcode の Playgroundで試すと true なんだけど
5:31 AM
REPL だと false になる不思議
5:31 AM
なんででしょうね...
Avatar
Optional<Any>.none is AnyObject
Avatar
それでも結果が違う
5:34 AM
@swift-5.2.5 Optional<Any>.none is AnyObject
Avatar
exit status: 1 with stderr:<unknown>:0: error: no such file or directory: 'Optional<Any>.none'
Avatar
使い方こうじゃないのか...
5:36 AM
@swift-5.2.5 Optional<Any>.none is AnyObject
Avatar
stderr:<stdin>:1:20: warning: 'is' test is always true Optional<Any>.none is AnyObject ^ <stdin>:1:20: warning: conditional cast from 'Optional<Any>' to 'AnyObject' always succeeds Optional<Any>.none is AnyObject ^ <stdin>:1:20: warning: expression of type 'Bool' is unused Optional<Any>.none is AnyObject ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
Avatar
@swift-5.2.5 print(nil as String? is AnyObject)
Avatar
truestderr:<stdin>:1:22: warning: 'is' test is always true print(nil as String? is AnyObject) ^ <stdin>:1:22: warning: conditional cast from 'String?' to 'AnyObject' always succeeds print(nil as String? is AnyObject) ^
Avatar
むむ
Avatar
22:51 niw@tpurr:~/Desktop $ cat a.swift let b: Bool = nil as String? is AnyObject print(b) 22:51 niw@tpurr:~/Desktop $ swiftc a.swift 2>/dev/null && ./a false (edited)
5:54 AM
むむむ...
5:58 AM
22:57 niw@tpurr:~/Desktop $ cat a.swift import Foundation let n: NSString = "a" let b: Bool = nil as String? is AnyObject print(b) 22:57 niw@tpurr:~/Desktop $ swiftc a.swift 2>/dev/null && ./a true (edited)
5:58 AM
trueになった...
5:58 AM
まじか...
5:58 AM
$ otool -L ./a ./a: /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1) /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1675.129.0) /usr/lib/swift/libswiftCore.dylib (compatibility version 1.0.0, current version 1103.8.25) /usr/lib/swift/libswiftFoundation.dylib (compatibility version 1.0.0, current version 0.0.0)
5:58 AM
Foundation.framework がリンクされてるかどうかで挙動がかわるっぽい? (edited)
6:01 AM
23:00 niw@tpurr:~/Desktop $ cat a.swift import Foundation let n: Data? = nil let b: Bool = nil as String? is AnyObject print(b) 23:00 niw@tpurr:~/Desktop $ swiftc a.swift 2>/dev/null && ./a false 23:00 niw@tpurr:~/Desktop $ otool -L ./a ./a: /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1) /usr/lib/swift/libswiftCore.dylib (compatibility version 1.0.0, current version 1103.8.25) (edited)
6:01 AM
えーっということは Foundation.framework がない場合の import Foundation では挙動が変わらないと... (edited)
Avatar
NSObjectへの暗黙変換が走る環境かどうかでAnyObjectへのキャストの可否は結果に差が出ます
Avatar
気持ちはわかるけど、なかなか怖い
Avatar
あんまり好きじゃない挙動の1つですね。
5:08 PM
任意の値をclassかどうか判別するのに type(of: someValue) is AnyObject.Type で見ないといけない
Avatar
これ最適化の有無で結果が変わるね。 $ pbpaste let b: Bool = nil as String? is AnyObject print(b) $ pbpaste|swiftc -suppress-warnings - && ./main false $ pbpaste|swiftc -suppress-warnings -O - && ./main true
11:56 PM
気持ちはわかる
Avatar
Foundation.frameworkをリンクしてるかどうかは関係ないぽい。 $ pbpaste|swiftc -suppress-warnings - && ./main && otool -L ./main false ./main: /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1) /usr/lib/swift/libswiftCore.dylib (compatibility version 1.0.0, current version 1103.8.25) $ pbpaste|swiftc -suppress-warnings -O - && ./main && otool -L ./main true ./main: /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1) /usr/lib/swift/libswiftCore.dylib (compatibility version 1.0.0, current version 1103.8.25) (edited)
Avatar
なるほど...?
12:15 AM
NSObject が現れるかどうかとか?
Avatar
あ、間違い。 (edited)
12:19 AM
いや、提示したログの検証手順が間違ってたけど、結果は会ってた。
12:21 AM
Linuxだと最適化に関係なくtrue $ pbpaste|docker-swift-run bash -c "swiftc -suppress-warnings - && ./main && ldd ./main" true linux-vdso.so.1 => (0x00007ffd56da9000) libswiftSwiftOnoneSupport.so => /usr/lib/swift/linux/libswiftSwiftOnoneSupport.so (0x00007f1bed03c000) libswiftCore.so => /usr/lib/swift/linux/libswiftCore.so (0x00007f1bec8e1000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1bec517000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f1bec2fa000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f1bec0f6000) libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f1bebd74000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1beba6b000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f1beb855000) libicui18nswift.so.65 => /usr/lib/swift/linux/libicui18nswift.so.65 (0x00007f1beb335000) libicuucswift.so.65 => /usr/lib/swift/linux/libicuucswift.so.65 (0x00007f1beaf3e000) libicudataswift.so.65 => /usr/lib/swift/linux/libicudataswift.so.65 (0x00007f1be928f000) /lib64/ld-linux-x86-64.so.2 (0x00007f1bece61000)
12:22 AM
$ pbpaste|docker-swift-run bash -c "swiftc -suppress-warnings -O - && ./main && ldd ./main" true linux-vdso.so.1 => (0x00007ffeea9c8000) libswiftCore.so => /usr/lib/swift/linux/libswiftCore.so (0x00007f4e73cb0000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4e738e6000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f4e736c9000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4e734c5000) libicui18nswift.so.65 => /usr/lib/swift/linux/libicui18nswift.so.65 (0x00007f4e72fa5000) libicuucswift.so.65 => /usr/lib/swift/linux/libicuucswift.so.65 (0x00007f4e72bae000) libicudataswift.so.65 => /usr/lib/swift/linux/libicudataswift.so.65 (0x00007f4e70eff000) libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f4e70b7d000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4e70874000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f4e7065e000) /lib64/ld-linux-x86-64.so.2 (0x00007f4e74230000)
Avatar
print()を使わない様にすると最適化の有無に関係なくfalse $ pbpaste let b: Bool = nil as String? is AnyObject $ pbpaste|swift -frontend -repl -sdk (xcrun -sdk macosx -show-sdk-path) 2>&- // b : Bool = false $ pbpaste|swift -frontend -repl -sdk (xcrun -sdk macosx -show-sdk-path) -O 2>&- // b : Bool = false (edited)
12:39 AM
それにimport Foundationを追加すると最適化の有無に関係なくtrue terminal.sh-session $ pbpaste import Foundation let b: Bool = nil as String? is AnyObject $ pbpaste|swift -frontend -repl -sdk (xcrun -sdk macosx -show-sdk-path) 2>&- // b : Bool = true $ pbpaste|swift -frontend -repl -sdk (xcrun -sdk macosx -show-sdk-path) -O 2>&- // b : Bool = true
12:43 AM
let b: Bool = nil as String? is AnyObject
  • 明示的にimport Foundationするとtrue
  • 明示的にimport Foundationしなくても、print()を使ってる場合、最適化ありでtrue、無しでfalse
(edited)
Avatar
むむむ、
12:46 AM
print()...
Avatar
Kishikawa Katsumi 3/30/2020 12:48 AM
print()して見ようとすると挙動が変わるのなかなか難しい問題だな
Avatar
REPLだとimport Foundation前に評価すると、インポート前も後もfalse $ swift Welcome to Apple Swift version 5.2 (swiftlang-1103.0.32.1 clang-1103.0.32.29). Type :help for assistance. 1> let a: Bool = nil as String? is AnyObject a: Bool = false 2> import Foundation 3> let b: Bool = nil as String? is AnyObject b: Bool = false 4> ^D 評価前にimport Foundationするとtrue $ swift Welcome to Apple Swift version 5.2 (swiftlang-1103.0.32.1 clang-1103.0.32.29). Type :help for assistance. 1> import Foundation 2> let a: Bool = nil as String? is AnyObject a: Bool = true
Avatar
@swift-main -Osize struct S { } struct T { let s: S } class C { func method() -> Any { let t = f() let r = (t != nil) ? 1 : nil return (r, t?.s) } func f() -> T? { return T(s: S()) } }
Avatar
swiftNightly BOT 4/2/2020 11:18 PM
exit status: 1 with stderr:<stdin>:1:1: error: extraneous '}' at top level } ^ <stdin>:4:12: error: use of undeclared type 'S' let s: S ^ <stdin>:15:21: error: use of unresolved identifier 'S' return T(s: S()) ^
Avatar
ふへ
11:19 PM
なぜ...
11:19 PM
@swift-nightly -Osize struct S { } struct T { let s: S } class C { func method() -> Any { let t = f() let r = (t != nil) ? 1 : nil return (r, t?.s) } func f() -> T? { return T(s: S()) } }
11:20 PM
あれ、これは動かない、、、
11:20 PM
@swift-main -Osize struct S { } struct T { let s: S } class C { func method() -> Any { let t = f() let r = (t != nil) ? 1 : nil return (r, t?.s) } func f() -> T? { return T(s: S()) } }
Avatar
swiftNightly BOT 4/2/2020 11:20 PM
no output
Avatar
おお? crashしない
11:21 PM
@swift-5.2.5 -Osize struct S { } struct T { let s: S } class C { func method() -> Any { let t = f() let r = (t != nil) ? 1 : nil return (r, t?.s) } func f() -> T? { return T(s: S()) } }
Avatar
no output
Avatar
-Osize無視されるのかな...
11:23 PM
swiftcをこれでクラッシュできるはずなんだけど。
Avatar
Immediate モードだと IRGen した後 LLVM 通さずに JIT 実行してしまうからですかね。
👍 1
Avatar
nightlyダウンロードしてた
11:29 PM
Swift ビルドするのはしんどい...
11:29 PM
わーい
11:29 PM
クラッシュした
Avatar
siloptimizerのバグっぽいなあ
12:11 AM
tuple_element_addr が分岐で違うほうのうやつを見ちゃってる
Avatar
optimizeを一つだけオフとかできるのかなあ
Avatar
omochimetaru 4/3/2020 6:26 AM
できますよ
Avatar
ConditionForwardingを切りたい
Avatar
omochimetaru 4/3/2020 6:27 AM
ちょっとまってて
Avatar
omochimetaru 4/3/2020 6:28 AM
$ swiftc -Xllvm -sil-disable-pass=<パスの名前> a.swift 多分こう (edited)
💯 1
6:29 AM
パスの名前は $ swiftc -Xllvm -sil-print-pass-name=true a.swift を一度流してデバッグログを見たらわかる気がする
6:30 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
6:30 AM
情報はこのへんとテストケース。 (edited)
Avatar
Passes.defみてた
Avatar
omochimetaru 4/3/2020 6:30 AM
ああ、そっちがいいですね。
Avatar
ConditionForwardingではなかったか...
Avatar
SILCombine か...
6:50 AM
めちゃでかい...
Avatar
JumpThreadSimplifyCFG だけdisableする、でも大丈夫だな
7:08 PM
5.3でwindowsサポートするらしい
Avatar
Kishikawa Katsumi 4/3/2020 7:32 PM
ね。なんか急に進んだなあという感じ。
Avatar
imaginary WWDC で Gates が登壇してみたいなことがあったのかもしれない (edited)
Avatar
omochimetaru 4/4/2020 4:23 AM
6までかかると思ってた たしかに進捗的にはもう出すだけだけど
4:25 AM
実際にどのくらい使ってみたんだろう
3:54 AM
@jckarter is there any way to get a value of type Any to pass itself to an unconstrained generic function to recover its type (without using the runtime directly)?
3:54 AM
3:56 AM
// RUN: %target-typecheck-verify-swift protocol P { } func foo<T: P>(_: T) {} func bar<T: P>(_: T.Type) {} func open(existential: P, mutExistential: inout P) { _openExistential(existential, do: foo) _openExistential(type(of: existential), do: bar) _openExistential(mutExistential, do: foo) _openExistential(type(of: mutExistential), do: bar) }
3:56 AM
existential self openテクを使わなくてもopenできる
Avatar
norio_nomura 4/14/2020 4:06 AM
@swift-4.0.3 @swift-4.1.3 @swift-4.2.4 @swift-5.0.3 @swift-5.1.5 @swift-5.2.5 protocol P { } func foo<T: P>(_: T) {} func bar<T: P>(_: T.Type) {} func open(existential: P, mutExistential: inout P) { _openExistential(existential, do: foo) _openExistential(type(of: existential), do: bar) _openExistential(mutExistential, do: foo) _openExistential(type(of: mutExistential), do: bar) }
Avatar
no output
Avatar
no output
Avatar
no output
Avatar
no output
Avatar
no output
Avatar
no output
Avatar
omochimetaru 4/14/2020 4:06 AM
4.0マジ
Avatar
omochimetaru 4/14/2020 5:07 PM
This PR implements an alternative to the syntax proposed in SE-0279, allowing an initial unlabeled trailing closure to be followed by an arbitrary number of labeled-closure postfixes.
5:08 PM
func mixed_args_2(_: () -> Void, a: () -> Void, _: () -> Void) {} mixed_args_2 {} a: {} _: {}
5:09 PM
SE-0279 のスレで出てきた別文法の(実験?)実装が出てる・・・
5:11 PM
0279はプロポーザル通りの実装もメリメリ進んでてそのまま行くんかな〜と思ってたけど、 いろいろ試してるのかな。
6:04 PM
argといえば...
6:04 PM
しんどい
Avatar
omochimetaru 4/14/2020 6:04 PM
あれ? os_log ってそもそも可変長の CVarArg... が提供されてますよね?
Avatar
CVarArg...CVarArg... のまま渡せない。
Avatar
omochimetaru 4/14/2020 6:05 PM
引数の順番を並び替えたかったってことですか?
Avatar
(すくなくとも発見できなかった)
Avatar
omochimetaru 4/14/2020 6:05 PM
はい、可変長引数の転送は確かにできないです。
Avatar
まず、os_log はiOS12以前と以降で引数の順番がかわっててですね
6:06 PM
iOS12以前のやつはキモい順番なので使いたくないんですが
Avatar
omochimetaru 4/14/2020 6:06 PM
マジw
6:06 PM
しらなかた。
Avatar
os_log(message, type:, ...) はiOS12以前でも動く
6:07 PM
os_log(type:, log:, message, CVarAg ...) (よりナチュラル)なのはiOS12以降
Avatar
omochimetaru 4/14/2020 6:07 PM
書式文字列とパラメータの間にtypeがあるのヤバいな。
Avatar
そこでこのようなキモいwrapperを書くと幸せ(かつ将来の以降が簡単)なんだけど
Avatar
omochimetaru 4/14/2020 6:07 PM
なるほどですね
Avatar
キモい
6:08 PM
Tuple1Tuple22 を思い出す実装となっています
Avatar
omochimetaru 4/14/2020 6:08 PM
22 まであるのScalaっぽいな
6:08 PM
あれ、17だっけ
Avatar
22以上は設計の問題という話
6:09 PM
22だったはず
6:09 PM
21かな?なんかそれくらい
Avatar
omochimetaru 4/14/2020 6:09 PM
ですよね なんか変な数
6:09 PM
配列から可変長パラメータへのsplat展開は
Avatar
va_listなos_logがあればwith_valistで解決するんだけど...
Avatar
omochimetaru 4/14/2020 6:09 PM
まあまあ話題に上がるんですけどあんまり進まないっすね
6:09 PM
va_list版は公開されてないんですね。
Avatar
os_log系以外では多分使われない?
6:10 PM
そうなんですよ。_swift_os_logとかそんな名前
Avatar
omochimetaru 4/14/2020 6:10 PM
Cの全ての可変長引数関数はva_list版を提供すべきだと思うんだけど。
6:10 PM
転送できないから。C言語だけ考えたときにも。
Avatar
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 4/14/2020 6:10 PM
あ、まあプリプロセッサ展開はあるけど
Avatar
os_logがそもそもマクロだから...
Avatar
omochimetaru 4/14/2020 6:14 PM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
6:14 PM
よくわかんなかった。
6:17 PM
ObjC版はマクロだからこんな感じのあれに展開されてるのかな。 (edited)
Avatar
_os_log_implがAPIの実態で、os_logはAPIでマクロだったはず
Avatar
omochimetaru 4/14/2020 6:21 PM
なるほど。。
Avatar
os_logがマクロなのは、loggingを無効にしたときにマクロレベルで抹消するためと思われる
6:21 PM
swiftからつかったらどうなるのよという部分はよくわからないけれど
6:22 PM
到達できないようになって最適化で消えるのかな...
6:22 PM
という気持ちだけある
Avatar
omochimetaru 4/14/2020 6:22 PM
os_log向けのoptimizer passがあった気がするな。
Avatar
やはり
Avatar
omochimetaru 4/14/2020 6:23 PM
PASS(OSLogOptimization, "os-log-optimization", "Optimize os log calls")
Avatar
os_logはいろいろ厳しい
Avatar
omochimetaru 4/14/2020 6:23 PM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
tryEliminateOSLogMessage
Avatar
omochimetaru 4/14/2020 6:25 PM
ビルドスイッチとはまた別の最適化っぽい?
6:25 PM
書式文字列の中に定数を埋め込むとかなんとか
Avatar
ですね
6:27 PM
消える機能みたいなのはないのかも。
Avatar
omochimetaru 4/14/2020 6:30 PM
#define os_log_with_type(log, type, format, ...) __extension__({ \ os_log_t _log_tmp = (log); \ os_log_type_t _type_tmp = (type); \ if (os_log_type_enabled(_log_tmp, _type_tmp)) { \ OS_LOG_CALL_WITH_FORMAT(_os_log_impl, \ (&__dso_handle, _log_tmp, _type_tmp), format, ##__VA_ARGS__); \ } \ })
6:31 PM
API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0)) OS_EXPORT OS_NOTHROW OS_WARN_RESULT OS_PURE bool os_log_type_enabled(os_log_t oslog, os_log_type_t type);
6:31 PM
スイッチになってるos_log_type_enabled がシステムAPIなので
6:31 PM
ビルド時の削除は無いかも?
6:31 PM
#define os_log(log, format, ...) \ os_log_with_type(log, OS_LOG_TYPE_DEFAULT, format, ##__VA_ARGS__)
6:32 PM
#define os_log は一箇所しか無さそう。
Avatar
おってみたらそうですね
6:32 PM
自分で #define したら消せる
Avatar
omochimetaru 4/14/2020 6:33 PM
なるほど!w
6:33 PM
そうするとこれがマクロなのは、インライン化の強制と、可変長引数の転送のゼロコスト化が目的かな?
Avatar
それっぽいですね
6:35 PM
いづれにせよ、swiftから使うのはいろいろしんどい...
Avatar
omochimetaru 4/17/2020 2:15 AM
The second review of SE-0279 — Multiple Trailing Closures begins now and runs through April 24, 2020. This is the second review, with a modified proposal. The core team has considered the feedback from the first review and believes that: the underlying motivation for the p...
Avatar
omochimetaru 4/17/2020 2:22 AM
>>2 で jroseさんがラベルの消える想定してる位置違くない?の件を突っ込んでてワロタ
Avatar
https://forums.swift.org/t/se-0279-multiple-trailing-closures-amended/35435/2
it also feels weird to me that all of these are the same call:
foo(bar: { provideBar() }, baz: { provideBaz() }, garply: { provideGarply() }) foo(bar: { provideBar() }, baz: { provideBaz() }) { provideGarply() } foo(bar: { provideBar() }) { provideBaz() } garply: { provideGarply() } foo() { provideBar() } baz: { provideBaz() } garply: { provideGarply() }
I understand how existing syntax encourages removing the argument label from the first trailing closure rather than the final trailing closure, but I'm worried that this puts us at odds with APIs designed for pre-Swift-5 code, which would put the "heaviest" closure last and "l...
2:22 AM
同じの見てたw
2:23 AM
omochimetaru が言ってるのは↓の方か。
I understand how existing syntax encourages removing the argument label from the first trailing closure rather than the final trailing closure, but I'm worried that this puts us at odds with APIs designed for pre-Swift-5 code, which would put the "heaviest" closure last and "light" ones in the middle in order to make existing trailing closure syntax feel natural
Avatar
omochimetaru 4/17/2020 2:23 AM
そう。
2:24 AM
詳細のところのfooの例も面白いですね。結局、好きなところを一つだけラベル消せるのね
2:25 AM
お〜 ラトナーがシュッと+1してる
Avatar
これヤバさあるよねw < 好きなところを一つだけ消せる
2:25 AM
初っ端から元Apple社員の jrose さんによる反論が出て「いいね」集めまくってて荒れそうだ・・・。 (edited)
Avatar
omochimetaru 4/17/2020 2:25 AM
ラトナーが反対してたポイントは直ってるから態度に一貫性がある
2:25 AM
>>2 にハート多いの面白いですねw
Avatar
なるほど。 < ラトナー
Avatar
omochimetaru 4/17/2020 2:27 AM
前スレはラトナー vs Dorg(プロポーザルオーサー) なシーンがあってアツかった
Avatar
まあでも元から traling closure のラベル消せるのにも違和感あったし、どこでも消せるのが変ってのは今更な気もするなぁ。 (edited)
Avatar
omochimetaru 4/17/2020 2:28 AM
まあ確かに。一個消えるのはもともとあった謎要素だから、
2:28 AM
それが拡張された結果、消しゴムが移動するようになったのは
2:28 AM
自然か?w
Avatar
せめて既存 API と衝突しないように、ラベルを省略しないオプションがあってもいいと思うんだけどなぁ。
2:29 AM
というか、これサポートされたからって使う? animate でも普通に () で書きそう・・・。
Avatar
omochimetaru 4/17/2020 2:30 AM
僕はXcodeのインデントが治るのとセットなら使いますね
2:30 AM
記号やネストの数が減るやつは使える限り使ってる
2:31 AM
今はtrailing closureすら、Xcodeが変なインデントするケースでは使ってないけど。
2:31 AM
インデントがちゃんとするのは前提で。
Avatar
view.animate(withDuration: 5.0, animations: { // some code }, completion: { isFinished in // some code }) ↑で困ってないんだよなぁ。
2:32 AM
ネストって言ってもインデント深くなってないし。
Avatar
omochimetaru 4/17/2020 2:33 AM
末尾の }) は目がちょっと目がチカチカする。
2:34 AM
2つ重なって }) }) とかなると やだ。
2:35 AM
ま〜でも animate の場合は、 completion も使う時は ( ) で書く気もするな なんか不揃いで気持ち悪いから。
Avatar
カーソル併せたら () の対応示してくれて、クロージャがたくさんのときは、かえってどこからどこまで関数コールだったのかわかりやすくて良い気も。 (edited)
2:36 AM
SE-0279 の提案に偶然ぴったりの animations: 省略がマッチしてる animate でもそれなんだから、他の API で使いたくなるのかな・・・。
Avatar
ちなみに、インデントは次のバージョンではこうなります (2スペース設定で) view.animate(withDuration: 5.0, animations: { // some code }, completion: { isFinished in // some code }) view.animate(withDuration: 5.0, animations: { // some code }, completion: { isFinished in // some code }) view.animate( withDuration: 5.0, animations: { // some code }, completion: { isFinished in // some code }) (edited)
Avatar
Kishikawa Katsumi 4/17/2020 2:38 AM
view.animate( withDuration: 5.0, animations: { // some code }, completion: { isFinished in // some code }) ^ 私はこの中ならこう書く。インデントだけの好みなら。
2:38 AM
1番上もアリ。
Avatar
@Kishikawa Katsumi 二つ目の // some code のインデントはミスですよね?
Avatar
↑僕がミスったから💦
Avatar
Kishikawa Katsumi 4/17/2020 2:39 AM
2番目はカッコの次に引数の頭が揃うわけではない? (edited)
Avatar
ああ、なるほど。
Avatar
ついにクロージャーのインデントが奇麗に!
2:40 AM
今まで手動でそのインデントにしてました
2:40 AM
2番目の奴
2:40 AM
個人的には最後の}と)を改行するのが好きだけどまあ誤差
Avatar
Kishikawa Katsumi 4/17/2020 2:41 AM
私も手で直して // Default .receive(on: RunLoop.main) .sink { [weak self] in guard let self = self else { return } self.coordinator.onThumbnailCollectionViewSelectionChange() } .store(in: &cancellables) // Modified thumbnailCollectionView.onSelectionChange .receive(on: RunLoop.main) .sink { [weak self] in guard let self = self else { return } self.coordinator.onThumbnailCollectionViewSelectionChange() } .store(in: &cancellables) ^ こうしてた。 (edited)
Avatar
昨日 tarunon さんが挙げてた↓とかも辛そうな気が・・・。それとも Button にとっては action こそが本質なのかな。 Button { print("hello world") } label: { HStack { ... } }
Avatar
Kishikawa Katsumi 4/17/2020 2:41 AM
(デフォルトだと最後の.storeが左に寄っちゃう。)
Avatar
@tarunon 2番目、メソッド名が長いと辛くないですか?
Avatar
うーん、必要に応じて.の前に改行挟むので
Avatar
Kishikawa Katsumi 4/17/2020 2:43 AM
2番目は1個のクロージャでいきなり始まりが右に飛んでしまうのが(私は)読みにくいですね。 (edited)
Avatar
view .animate( withDuration: 5.0, animations: { // some code }, completion: { isFinished in // some code } ) こういう書き方が多かったかな。メソッドチェーンあるなら確実にこうする。
Avatar
foo.bar.baz .superUltraVeryLongLongLongNameMethod(a: 42, b: "XYZ", c: true)
Avatar
あ、2番目じゃなくて3番目だった
Avatar
Kishikawa Katsumi 4/17/2020 2:45 AM
koherさんの例だと、〜Method(のところで(最初の引数ラベルの前)(私は)改行します。 (edited)
Avatar
それだと 3 番目ですよね? tarunon さんも 3 番目だし、 2 番目ユーザーはいないのかな?
Avatar
Kishikawa Katsumi 4/17/2020 2:46 AM
最初は挙動を知らなかったから2 番目で書いてましたが。。。
Avatar
僕も長い場合は 3 番目も使います。 ) を次の行にしてましたが・・・。
Avatar
Kishikawa Katsumi 4/17/2020 2:47 AM
Appleのコード見てるとイニシャライザとかカッコの後で改行してるなあと思ってやってみたら「なるほど」という感じで転向しました。 (edited)
Avatar
なので tarunon さんが書いた animate の例とまったく同じかな。
2:49 AM
. 前で改行するなら tarunon さんのとまったく同じで、改行しないなら view.animate( withDuration: 5.0, animations: { // some code }, completion: { isFinished in // some code } )
2:50 AM
もし trailing comma が採用されるなら ) の前に改行して , おいた方がうれしい気が。
Avatar
改行あると各コンテキストが全てインデントによって整理されるので嬉しい
👍 1
2:51 AM
まあ無くても終端はわかるのでいいっちゃいいんですが
Avatar
↓とかも ] 前に改行するしなぁ。 let a = [ 2, 3, 5, ]
Avatar
omochimetaru 4/17/2020 2:53 AM
ちなみに、インデントは次のバージョンではこうなります (2スペース設定で)
おおお
Avatar
僕は圧倒的に)前改行無しです。。
Avatar
@rintaro 仮に trailing comma がサポートされた場合はどうですか? foo( a: 42, b: "XYZ", c: true, ) foo( a: 42, b: "XYZ", c: true, d: 0.0, ) (edited)
Avatar
omochimetaru 4/17/2020 2:55 AM
メソッドチェーンしてるときが特に変になるからそれも気になる。
Avatar
↑デフォルト値ある引数に値渡すときに、 diff がその行で完結する。 (edited)
Avatar
trailing comma 採用して欲しくない理由があって、 foo.bar( arg: 1<カーソル>) この状態からリターンキー押したときに、カンマがあれば arg: に揃える、無ければ foo に揃えるっていうのが出来るんですが、trailing comma 採用すると判断がつかない。 (edited)
Avatar
後ろの)で判定するのじゃだめなんですか?
Avatar
なるほどー、考えたことないポイントでした。おもしろい・・・。
Avatar
Kishikawa Katsumi 4/17/2020 2:59 AM
コードフォーマットは書いてる途中はどうでもいいので保存したタイミングとかで一定のフォーマットに整ってくれた方が嬉しいですね。よくあるPrettierの挙動。
Avatar
foo.bar( arg: 1, <カーソル>) この状態で、例えば 1 入力して終了したいとき、それだけだとインデントがトリガーされないんですよね。
3:02 AM
じゃあ配列リテラルはどうなんだっていう話ではあります。
Avatar
常に)に揃えて改行して、改行したその先で何かタイプされたらその時点でインデントするみたいな、遅延評価だとうまくいく気がする
Avatar
行頭になにか入力されたらインデントトリガーするようになれば良さそう。
Avatar
foo.bar( arg:1|) foo.bar( arg:1 |) foo.bar( arg:1, b|) こういう感じ (edited)
3:05 AM
,も補完するのかな?w (edited)
Avatar
今は Preferences > Text Editing > Syntax Aware Editing > Indent when typing でチェック入ってるものしかトリガーしないのです。
Avatar
僕は ) 前改行派だから、↓こうなってくれたら幸せな気が。 foo.bar(|) ↓改行 foo.bar( | ) で、これなら (|) 以外でカーソル後に ) が来ることがないから、 foo.bar( a: 42,| ) ↓改行 foo.bar( a: 42, | ) のケースしかない?
3:09 AM
あー、一行で書いてたのを複数行に直すシナリオはあるけど、そのときは結局直さないといけなさそうな。
Avatar
最初の状態からリターンキーで次の状態に移行しちゃうと、)前改行なし派が怒りそう。
Avatar
それは設定で変えられるようにするかでしょうか。でも岸川さんの言うように、フォーマッターがよろしくやってくれたらそれでいいですね。
Avatar
Kishikawa Katsumi 4/17/2020 3:12 AM
私は書いてる途中は複雑なことはしてくれなくていいです。この例だと、 foo.bar(|) foo.bar( |)
Avatar
Eclipse 時代に Java のフォーマッターに慣れ親しんでたので、標準が機械的に決めてくれるなら従います。
Avatar
Kishikawa Katsumi 4/17/2020 3:12 AM
こうかな。
3:14 AM
カッコのあととかはインデントを下げる、というのはやって欲しいけど(さすがに書きにくい)、あとは書き終わったら保存するのでそこで変わってくれればいいです。
Avatar
保存時に自動フォーマット大抵はうれしいけど、一部フォーマット変えてほしくないコードとかあるから難しいですよね😢 ↓みたいな。 var board = ReversiBoard([ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "o", "x", "-", "-", "-", "-", "-", "-", "x", "o", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", ])
3:17 AM
Eclipse はこういうやつも破壊してきました・・・。
Avatar
Kishikawa Katsumi 4/17/2020 3:18 AM
そういうのは // prettier-ignore っていうのがあるからそれを付けます (edited)
Avatar
なるほど。
Avatar
Kishikawa Katsumi 4/17/2020 3:19 AM
JSのprettierのデフォルトだと三項演算子を積極的に改行しようとするので、たまに付けますね(私は)。
3:20 AM
まあXcodeのできるだけ現状の状態を汲み取ってくれる、みたいな挙動はけっこう好きですが。
Avatar
フォーマットとインデントの違いですね。インデントは行頭の空白文字しか調整しないけど、フォーマットは改行位置も行中空白文字も変えてくる。
3:23 AM
僕はインデンタがまともなら 選択して Ctrl + i でとりあえず十分です。
Avatar
Kishikawa Katsumi 4/17/2020 3:23 AM
なるほどXcodeでペーストしたときに実行されてるのは「Re-indent」でFormatはやってない、、ということなんですね。
Avatar
はい、Xcodeには現状フォーマットの機能は無いです。
Avatar
行中の空白文字は整えてくれるとうれしいですね。抜けちゃってるケースがあると気になるし。
Avatar
Kishikawa Katsumi 4/17/2020 3:25 AM
なるほど。前にフォーマッタを作ったときにできるだけXcode風の現状の様子を生かしつつフォーマットしよう、みたいなのを作ったけど、あれはインデントとフォーマットを分ければ済んだ話だったのか。。。
Avatar
1 ... 1001...100 と書いてしまったり。
Avatar
swift-formatがXcodeに導入されるのを祈りましょう。
🥺 1
🙏 1
Avatar
Kishikawa Katsumi 4/17/2020 3:29 AM
🙏
Avatar
Multiple trailing closure ですが、 Section { Text("Foo") } header: { /* some code */ } footer: { /* some code */ } Section { Text("Foo") } header: { /* some code */ } footer: { /* some code */ } どちらが良いと思います?
⬇️ 1
Avatar
Kishikawa Katsumi 4/17/2020 3:34 AM
後者かな。。。?あまり自信ないけど、たぶん後者。
3:35 AM
いや、前かな。。。
3:35 AM
(どっちでも良さそう😅
Avatar
if foo { /* some code */ } else { /* some code */ } っていうのを考えると前者なのかなー。いずれにしても、こういう風に書かれることはほとんどなさそうですね。 😅
Avatar
僕も後者ですねー。見た目は似てるけど文と式だし、区別されてた方が良さそうな気が。 (edited)
👍 1
Avatar
インデント絡みで言うと、もし時間あったらnightlyのツールチェーンで全選択 Ctrl + i 試してみてください。気に入らないインデントになったら bugs に是非!
Avatar
Kishikawa Katsumi 4/20/2020 9:01 AM
https://discordapp.com/channels/291054398077927425/291054454793306112/691905724468428811 ^ このデフォルトパラメータの有無(とトップレベル関数かどうか)でオーバーロードの解決が変わる事象について遅くなったけど聞いてみました。 https://bugs.swift.org/browse/SR-12630
Avatar
snapshot 2020-04-15 をXcode11.4.1に設定してインデントしてみたけど、一番気になってるやつは変わってなかった。 let files = try fm.contentsOfDirectory(at: dir, includingPropertiesForKeys: nil) .filter ({ (file) in var isDir = false return fm.fileExists(at: file, isDirectory: &isDir) && !isDir }).map { $0.lastPathComponent } ↑これはOK let files = try fm.contentsOfDirectory(at: dir, includingPropertiesForKeys: nil) .filter { (file) in var isDir = false return fm.fileExists(at: file, isDirectory: &isDir) && !isDir }.map { $0.lastPathComponent } ↑これが嫌 今度要望出します
Avatar
むむ、僕の環境 (Version 11.4 (11E146), Toolchain: Swift Development Snapshot 2020-04-19 (a)) ではこうなります。 let files = try fm.contentsOfDirectory(at: dir, includingPropertiesForKeys: nil) .filter { (file) in var isDir = false return fm.fileExists(at: file, isDirectory: &isDir) && !isDir }.map { $0.lastPathComponent } Trunk のスナップショットで試してます?
Avatar
omochimetaru 4/21/2020 4:01 PM
あ〜 こっちは5.2.2だから新しいの入ってないのか
4:01 PM
trunkじゃなかったです、すいません
4:02 PM
一番上がmasterだと勘違いした
💡 1
4:05 PM
let files = try fm.contentsOfDirectory(at: dir, includingPropertiesForKeys: nil) .filter { (file) in var isDir = false return fm.fileExists(at: file, isDirectory: &isDir) && !isDir }.map { $0.lastPathComponent }
4:05 PM
おお、きた
4:06 PM
てか2段下がるんですね。
Avatar
二段というか、let ではなくて files に対してインデントしていますね。理由としては
4:08 PM
let val1 = foo .bar(), val2 = 1 みたいなときに、letに相対しちゃうと例えば2スペースインデントだと let val1 = foo .var(), val2 = 1 になってしまう。 (edited)
Avatar
omochimetaru 4/21/2020 4:09 PM
なるほど〜
Avatar
let じゃない普通の代入のときには1インデントになります。 foo = bar .baz()
Avatar
omochimetaru 4/21/2020 4:15 PM
このツールチェインで作業したかったけど、ビルドしようとしたら別のところでコンパイラクラッシュしてしまった (edited)
Avatar
4:43 PM
↑masterをビルドすると GLKVector3Ex.swift で怪しいassertion failureしました
Avatar
超コーナーケースな Swift 5.2 の変な挙動見つけました。最適化の問題だと思います。 @swift-5.2.5 -O class Foo { private let deinitBody: () -> Void init(_ deinitBody: @escaping () -> Void) { self.deinitBody = deinitBody } deinit { deinitBody() } } func main() { var a = 42 var foo = Foo {} foo = Foo { a = -1 } let _ = foo // to ignore warnings print(a) } main()
Avatar
-1
Avatar
@swift-5.2.5 class Foo { private let deinitBody: () -> Void init(_ deinitBody: @escaping () -> Void) { self.deinitBody = deinitBody } deinit { deinitBody() } } func main() { var a = 42 var foo = Foo {} foo = Foo { a = -1 } let _ = foo // to ignore warnings print(a) } main()
Avatar
42
Avatar
@swift-5.1.5 -O class Foo { private let deinitBody: () -> Void init(_ deinitBody: @escaping () -> Void) { self.deinitBody = deinitBody } deinit { deinitBody() } } func main() { var a = 42 var foo = Foo {} foo = Foo { a = -1 } let _ = foo // to ignore warnings print(a) } main()
Avatar
42
Avatar
Swift 5.2 においてだけ、最適化有効にするだけで挙動が変わる。
Avatar
omochimetaru 4/22/2020 4:08 AM
deinitとprintの前後ですかね? (edited)
Avatar
はい。
4:08 AM
バグなのか許された最適化なのかわかりません。
Avatar
omochimetaru 4/22/2020 4:08 AM
Swiftはスタック変数の削除は
4:08 AM
使わないところですぐ消しても良いし、
4:09 AM
スコープ抜ける末尾でも良い
4:09 AM
そこは定まってないから
Avatar
へー
Avatar
omochimetaru 4/22/2020 4:09 AM
ある範囲まで寿命を引っ張りたいなら
4:09 AM
使用を明記する必要があります
4:09 AM
標準ライブラリの中だとたしかfixLifetimeって
4:10 AM
ユーティリティ関数でそれをやってる
Avatar
@swift-5.2.5 -O class Foo { private let deinitBody: () -> Void init(_ deinitBody: @escaping () -> Void) { self.deinitBody = deinitBody } deinit { deinitBody() } } func main() { var a = 42 var foo = Foo {} foo = Foo { a = -1 } defer { let _ = foo } print(a) } main()
Avatar
42
Avatar
とりあえず↑で引っ張れたけど、 let _ = foo は最適化で削除される可能性もあるかな?
Avatar
omochimetaru 4/22/2020 4:13 AM
let _ = a 式を削除して良いのかどうかは良く知らない 経験的には消えなくて、寿命引っ張れるんだけど
4:14 AM
最適化を無効化してある関数の呼び出しに渡すのが確実そう。
4:15 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
withExtendedLifetime これ使うのが良いのかな
Avatar
omochimetaru 4/22/2020 4:15 AM
Builtinだ・・・
4:15 AM
あ!それっぽい
Avatar
生存期間保証するためにはこの関数使うのがヨシ、みたいな
4:15 AM
ここでやった記憶ある
Avatar
おおお、こんな関数が・・・
Avatar
omochimetaru 4/22/2020 4:16 AM
koherもコメントしててワロタ
Avatar
koherさんディスカッションに参加してますよw
Avatar
omochimetaru 4/22/2020 4:17 AM
タルノンよく覚えてんなあ
Avatar
はい、それみてワラタ
Avatar
だいたい全部覚えてる
Avatar
すごい
Avatar
Kishikawa Katsumi 4/22/2020 7:52 PM
いつの間にかif文の条件の中のTrailing Closureがコンパイルできるようになってたんですね。紛らわしいからカッコをつけろ、って警告に変わった。
7:52 PM
結局直すことになるのは変わらないけど。
Avatar
@swift-5.2.5 if [true, false].reduce(true) { $0 || $1 } { print("Hello") }
Avatar
Hellostderr:<stdin>:1:31: warning: trailing closure in this context is confusable with the body of the statement; pass as a parenthesized argument to silence this warning if [true, false].reduce(true) { $0 || $1 } { ~~^ , )
Avatar
ほんとだ・・・。
Avatar
@swift-5.1.5 @swift-5.2.5 if true == [true, false].reduce(true) { $0 || $1 } { print("Hello") }
Avatar
Hello
Avatar
Hellostderr:<stdin>:1:39: warning: trailing closure in this context is confusable with the body of the statement; pass as a parenthesized argument to silence this warning if true == [true, false].reduce(true) { $0 || $1 } { ~~^ , )
Avatar
っていう5.1.5のバグを直してコンパイルエラーにすると、ソース互換性が崩れてしまうので、警告に統一しました。
Avatar
何事もなく通るようになってた時期があったんですね💧
Avatar
一番外側が trailing closure でのコールじゃない限り通ってましたね。僕の例だと == がAST上では外側です。
Avatar
あー、 == があるんですね。見落としてました。
Avatar
omochimetaru 4/24/2020 4:52 PM
Contribute to omochi/WeaselRoll development by creating an account on GitHub.
Contribute to omochi/WeaselRoll development by creating an account on GitHub.
Contribute to omochi/WeaselRoll development by creating an account on GitHub.
4:52 PM
3つのプロトコルが相互に参照しあってる定義を作ったら、Xcode11.4ではビルドできるけど11.3ではできなくて 微調整すると11.3でも11.4でも、 コンパイルエラーやらリンクエラーやらプロセスクラッシュやら
4:53 PM
ありとあらゆるコンパイラの死に方をして何もわからなくて2時間ほど溶かした・・・
4:53 PM
昔からこういうのできないけどそろそろいけるんじゃねえかと思ったら全然ダメだった、一度通った実装は針の穴を通すような成功例だった
4:54 PM
ワークアラウンドとしてprotocolの定義の方では循環するような関係を定義しないでおいて、 必要に応じてメソッドの実装するところで最低限の == 関係を注入するように書いたら行けた。
Avatar
Kishikawa Katsumi 4/24/2020 4:57 PM
ありとあらゆるコンパイラの死に方
恐ろしい
☠️ 1
Avatar
omochimetaru 4/24/2020 4:57 PM
全然通せなくて笑っちゃったw
Avatar
Kishikawa Katsumi 4/24/2020 4:58 PM
コンパイラを拷問する100の方法
4:58 PM
著: おもちメタル
Avatar
omochimetaru 4/24/2020 4:58 PM
イメージ的には CGPoint, CGSize, CGRect みたいな3つのグループを
4:58 PM
Point, Size, Rect と IntPoint, IntSize, IntRect みたいに
4:58 PM
他にも作れるようにしたかった。
Avatar
Kishikawa Katsumi 4/24/2020 5:01 PM
これは使い方はどうなるんですか? (edited)
5:01 PM
public struct IntRect: RectProtocol { public typealias Element = Int public typealias SizeType = IntSize public var origin: IntPoint public var size: IntSize public init(origin: IntPoint, size: IntSize) { self.origin = origin self.size = size } }
Avatar
omochimetaru 4/24/2020 5:01 PM
CGRectって要素がCGFloatなのが不便なので、FloatになってるRectとIntになってるIntRectを作りました
Avatar
Kishikawa Katsumi 4/24/2020 5:01 PM
これか。
Avatar
omochimetaru 4/24/2020 5:02 PM
あ、それtypealias足りて無さそう・・・
5:03 PM
画像サイズとか扱おうとした時に
5:03 PM
整数ピッタリじゃない可能性とかがあって気持ち悪いことがよくある
Avatar
Kishikawa Katsumi 4/24/2020 5:05 PM
これを実現するのにコンパイラとの格闘が必要になるんですね。
Avatar
omochimetaru 4/24/2020 5:05 PM
そうなんです
Avatar
Kishikawa Katsumi 4/24/2020 5:05 PM
もっと簡単にできても良さそうな気がするけど
Avatar
omochimetaru 4/24/2020 5:05 PM
public func transform<R: RectProtocol>(_ rect: R) -> [R.PointType] where R.Element: BinaryFloatingPoint { let points: [R.PointType] = [ rect.topLeft, rect.topRight, rect.bottomLeft, rect.bottomRight ] return points.map { (p) in transform(p.toGLKVector().to3(z: 0)).to2().toPoint().to(type: R.PointType.self) } }
5:05 PM
↑恩恵の一つがGLKMAtrix4.swift のこれで (edited)
5:06 PM
Rectを行列で変換すると(直角じゃない場合もあるので) 変換された4つの座標が返ってくるんですが
5:06 PM
CGRectを回転したらCGPointの配列が返ってくるし、 Rectを回転したらPointの配列が返ってくる って機能をひとまとめに実装できている。 (edited)
Avatar
Kishikawa Katsumi 4/24/2020 5:23 PM
そこでProtocol Extensionの恩恵が受けられるのですね
5:24 PM
Genericsの、かな?
Avatar
omochimetaru 4/24/2020 5:26 PM
両方混ざってますね。中に出てくる toGLKVector() とか toPoint() は Generic な Protocol Extension なので。
Avatar
Swifc かわいそう
Avatar
omochimetaru 4/25/2020 8:44 PM
かわいそうなのはこちらでは!?
Avatar
:シマリスくんの画像:
omomuki 1
Avatar
ObjectIdentifier 、同じプロセス中でもオブジェクトが解放された後なら被ることがあるのか。仕組み的に当たり前? @swift-5.2.5 class Foo {} var identifiers: Set<ObjectIdentifier> = [] for i in 0 ... 10 { identifiers.insert(ObjectIdentifier(Foo())) print("\(i): \(identifiers.count)") } (edited)
Avatar
0: 1 1: 2 2: 2 3: 2 4: 2 5: 2 6: 2 7: 2 8: 2 9: 2 10: 2 (edited)
Avatar
omochimetaru 4/29/2020 2:47 AM
そうですね。ObjectIdentifierが参照型を指している場合はretainする設計だったらそうはならなかったですけど
2:47 AM
まあ必要だったら自分でObjectIdentifierとAnyObjectのペアの型を作って管理すればよいから
2:47 AM
そういう意味では部品としては余計な副作用がなくてよかったと思う。
Avatar
うーん、思わぬバグを生んでしまうケースもありそうな?
Avatar
omochimetaru 4/29/2020 2:49 AM
まあそれは仕様を知らないとバグるのはなんでもそうでは
Avatar
CollectionIndex が内容変わると無効になる可能性があるのと同じような話だと思うのですが、ドキュメントに書いてあってもよさそう。
Avatar
omochimetaru 4/29/2020 2:53 AM
おお、その例は面白い。確かに同じだ。
Avatar
ポインタのint値を使っても同じことは起き得るので、被らないようにするのはコスパが悪そうな気がしますね
Avatar
コスパは悪いと思います。ただ、ドキュメントはほしいですね。 https://developer.apple.com/documentation/swift/objectidentifier
Avatar
ドキュメンテーション足すのもPR投げれるのでは
Avatar
なるほど。
2:56 AM
doc comment から生成されてるのか。
Avatar
だと思いました
Avatar
ドキュメンテーションの PR は英語添削がヤバそうですねw
Avatar
omochimetaru 4/29/2020 2:56 AM
今なら educational note というアツいやつがありますよ
2:56 AM
koher とかめちゃくちゃコントリビュートできそう
Avatar
omochimetaru 4/29/2020 3:01 AM
3:02 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
3:03 AM
GSoCにdiagnostics localizationのプロジェクトがあるから、おいおいコレの日本語版を作るタスクも発生するはず
Avatar
localization版はただの翻訳作業になりそう。そして、英語を書くと↓になりそう😂
3:04 AM
3:06 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 4/29/2020 3:06 AM
それ。
Avatar
英語ネイティブじゃなければ添削祭になるのはもう仕方ない、ドキュメントを足そうという最初の一手を入れるか入れないかでしかないので添削は甘んじて受けて良いと思うのですが
3:08 AM
足さなければ永遠に足されないままなので
Avatar
コードレビューと違って、ノンネイティブの自然言語による文章の添削はレビュー側にとっても高コストな気がするんですよね。それでも書いてもらった方がありがたいというのであれば PR ありだと思うんですが。
Avatar
「最初の一手を入れるかどうか」と言う判断が問題意識を持った人間にしか出来ないので、ここで誰かが手を入れなければ誰も手を入れない、と言うことです
Avatar
omochimetaru 4/29/2020 3:17 AM
きっとまたrayfixさんが直してくれる(?)
Avatar
w < rayfix さん (edited)
3:18 AM
「最初の一手を入れるかどうか」と言う判断が問題意識を持った人間にしか出来ない
確かにそれはそうなので、今回は一文足す程度でも良いし、 PR 送ってみるのが良さそうですね。
Avatar
omochimetaru 4/29/2020 3:19 AM
koher が出す話題がこれにちょうど良さそうなやつが多い気がするんですよね 今思い返してたんだけどArraySliceのインデックスがズレるやつとか。
3:20 AM
ただコンパイルエラーに起因して出てくるからどう仕込むかが難しいけど・・・ 多分Xcodeだと 「FixIt」みたいなかんじで「詳しく知る」みたいなボタンが出るんだと思う
Avatar
おもしろそうだし興味あるけど、やっぱり英語がネックだなぁ。ドキュメンテーションのための文章はクオリティが求められるだろうし。まあでも、それで PR で添削してもらえるのなら英語力向上には良さそうだ😅
Avatar
omochimetaru 4/29/2020 3:22 AM
気持ちはわかる。 プルリク出した時に、 「ここなんでこうなるの?」って聞かれて説明すると 「なるほどね、それコメントに書いといてよ」 って言われるんだけどそこで結構困る
3:23 AM
あとエラーメッセージ実装するときとかも・・・
Avatar
コード書くよりむずいよね💧
Avatar
omochimetaru 4/29/2020 3:25 AM
そう・・・
Avatar
何でも良ければ書けるけど、多分ネイティブが読むと「てにをは」がぐちゃぐちゃな日本語読んでる感じなんだろうなぁと・・・。
3:27 AM
不自然な言い回しや単語、前置詞チョイスとか。
Avatar
我々が日本語母語でない人間のてにをはぐちゃぐちゃテキストを見ても何も思わないのと一緒で、向こうもまあ修正しとこか、ぐらいにしか思わないんじゃないかしら (edited)
🦀 1
Avatar
まあ、今回の件やエラーメッセージくらいだとそうだと思います。 Educational Note みたいなのになってくると、小手先の修正ではどうにもならなくて、意図を読み取って全部書き直すみたいなことにならないかなと。
Avatar
norio_nomura 4/29/2020 3:31 AM
ObjectIdentifierをキャッシュのキーにして被ってバグったことある。 (edited)
😢 1
Avatar
norio_nomura 4/29/2020 3:41 AM
複数スレッドでメモリ確保・開放ってしてると、被って誤動作する頻度が下がって、見つけづらいバグになる。
Avatar
omochimetaru 4/29/2020 3:49 AM
キャッシュのキーにする場合、もしretainする仕様だったら、キャッシュのせいでオブジェクトがリークしてしまうから、
3:49 AM
その場合はweak retainしていてくれたら良かったやつですね。
Avatar
Hi all, Since it's come up again in discussion recently, I wanted to share my proposal for making Never a true bottom type in Swift. This is partially implemented here, though there remains work to be done before it's ready for review. In the meantime, I'd be interested in he...
🎉 2
4:59 PM
Nothing 相当かな
Avatar
ですね。
Avatar
Kishikawa Katsumi 5/5/2020 1:42 PM
https://github.com/apple/swift-evolution/blob/master/proposals/0279-multiple-trailing-closures.md Multiple trailing closureはいまだに賛否両論で、私が見える範囲だといやがる人の方が多そうに見える。 私自身はこれに関しては全然興味なくて、変わっても変わらなくてもどっちでも良くて決まったものを使うだけだけど、 これだけに限らず今後Swiftに変更を加える上でソースコードの破壊的変更をしない、ということにこだわらなくてもいいんじゃないかという意見には同意したい。
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
protocolのassociatedtypeにoverrideが付けられる様なんですけど、どういう意味付けか知ってたりしませんか? stdlibのCollection.Elementとかに付いてるんですけど、あんまりテストケースが無くてどういう使われ方をするのかいまいち分からない… https://github.com/apple/swift/blob/7e6d62dae4bae4eb3737a6f76c0e51534c1bcca3/stdlib/public/core/Collection.swift#L342
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
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 ...
Avatar
コメント5回位読み直してやっと少しわかりましたw
7:57 AM
@swift-main enum GenericElement {} protocol MySequenceP { associatedtype Element associatedtype Iterator: IteratorProtocol where Iterator.Element == Element func makeIterator() -> Iterator } struct MyDefaultIterator: IteratorProtocol { func next() -> GenericElement? { return nil } } protocol MyCollectionP: MySequenceP { override associatedtype Element associatedtype Iterator = MyDefaultIterator } struct MyCustomIterator: IteratorProtocol { func next() -> GenericElement? { return nil } } struct MyCollection: MyCollectionP { typealias Element = GenericElement func makeIterator() -> MyCustomIterator { return .init() } }
Avatar
swiftNightly BOT 5/8/2020 7:57 AM
exit status: 1 with stderr:<stdin>:23:8: error: type 'MyCollection' does not conform to protocol 'MySequenceP' struct MyCollection: MyCollectionP { ^ <stdin>:25:10: note: candidate has non-matching type '() -> MyCustomIterator' [with Iterator = MyDefaultIterator] func makeIterator() -> MyCustomIterator { ^ <stdin>:7:10: note: protocol requires function 'makeIterator()' with type '() -> MyDefaultIterator'; do you want to add a stub? func makeIterator() -> Iterator ^
Avatar
このとき MyCollection のIteratorを推論する材料として makeIterator が使われないので、assoctypeのデフォルト型と一致せず失敗するが、
8:00 AM
@swift-main enum GenericElement {} protocol MySequenceP { associatedtype Element associatedtype Iterator: IteratorProtocol where Iterator.Element == Element func makeIterator() -> Iterator } struct MyDefaultIterator: IteratorProtocol { func next() -> GenericElement? { return nil } } protocol MyCollectionP: MySequenceP { override associatedtype Element associatedtype Iterator = MyDefaultIterator // Added override func makeIterator() -> Iterator } struct MyCustomIterator: IteratorProtocol { func next() -> GenericElement? { return nil } } struct MyCollection: MyCollectionP { typealias Element = GenericElement func makeIterator() -> MyCustomIterator { return .init() } }
Avatar
swiftNightly BOT 5/8/2020 8:00 AM
no output
Avatar
こうすると通るようになるのか
Avatar
Kishikawa Katsumi 5/13/2020 4:47 AM
https://discordapp.com/channels/291054398077927425/291054454793306112/692696352810860564 ^ この @Published のプロパティを直接変更してもdidSetが呼ばれない件、Xcode 11.5で元の挙動に戻ってますね。
Avatar
ほほー。👀 (edited)
Avatar
protocolのデフォルト実装みたいなのを持たせる方法ってあるですかねー。
1:02 AM
ええと、
Avatar
omochimetaru 5/15/2020 1:02 AM
extension P { func f() {} } ? (edited)
Avatar
そうじゃなくて (edited)
1:03 AM
この日本語はだめだ、えっと
Avatar
omochimetaru 5/15/2020 1:03 AM
Avatar
super呼びたい的な
Avatar
protocol P があったときに、struct DefaultP: P みたいなのがあるとして
1:03 AM
この DefaultP の所在というか,
1:04 AM
val p: P = .default ってできたらいいなっていうか
Avatar
omochimetaru 5/15/2020 1:04 AM
ないですね enum Ps { static var default { DefaultP() } } とかでごまかすしか
1:04 AM
あ、まてよ
Avatar
enum ...
1:05 AM
(あと、val じゃなくて let)
Avatar
extension P { static var default: P { DefaultP() } } ↑こんな感じ? (edited)
Avatar
RxSwiftのDisposableなんかはおもちさんのenumの方法に近い実装になってますね
Avatar
omochimetaru 5/15/2020 1:06 AM
1:06 AM
だめかあ
Avatar
existentialにstaticメソッドは持たせられないので
Avatar
直感的な方法はダメだったんですよねえ
Avatar
omochimetaru 5/15/2020 1:06 AM
P.self が存在しないからできないんだなあ
Avatar
そうだった
Avatar
現実解はs付けたenumになると思います
Avatar
厳しい...
Avatar
あとはDIで注入させるとか?
Avatar
omochimetaru 5/15/2020 1:08 AM
SwiftUIで
1:08 AM
むりやりな方法でデフォルトっぽいのやってなかったっけ
1:08 AM
StaticValue<T: P> みたいなやつ
Avatar
むむ?
Avatar
omochimetaru 5/15/2020 1:09 AM
結局廃止されたんだっけな、なんだっけ
Avatar
DIを常に要求するっていうてもありますが、なんていうかうーん使い勝手が。
Avatar
あとは無理やり型消去した AnyP.defaultP を作るとか?
Avatar
omochimetaru 5/15/2020 1:13 AM
SwiftUIのリファレンス見てきたけど廃止されている気がする
Avatar
SwiftUI であったのは StaticMember ですね。廃止されました。
Avatar
omochimetaru 5/15/2020 1:13 AM
StaticMemberか。
1:14 AM
あれがまさに、protocolを受け取るところで .red とかやるためのものだった気がする、違うっけ
1:14 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 ...
1:14 AM
protocol ColorStyle { typealias Member = StaticMember<Self> } extension StaticMember where Base : ColorStyle { static var red: RedStyle.Member { return .init(.init()) } static var blue: BlueStyle.Member { return .init(.init()) } } extension View { func colorStyle<S : ColorStyle>(_ style: S.Member) -> some View { ... } } MyView().colorStyle(.red) MyView().colorStyle(.blue)
1:16 AM
これの問題点は、消費側で <S: ColorStyle> に対して、 (_ s: S)(_ s: S.Member) の両方をオーバーロードしておかないといけないことだけど
Avatar
変数はダメだけど、引数でDefaultPをとる実装をオーバーロードすると、確かに引数だけなら .default が使えそうですね
Avatar
ふむー
Avatar
omochimetaru 5/15/2020 1:21 AM
確かにオーバーロードするんだったら DefaultP を取るだけが楽か。
Avatar
implicit type conversion ってないですよね
Avatar
omochimetaru 5/15/2020 4:01 AM
ないです
Avatar
toNankanoKata(): T (edited)
4:02 AM
みたいなの足してるのが一般的?
Avatar
omochimetaru 5/15/2020 4:02 AM
<T: CustomStringConvertible> T こういうので受け取れば、変換っぽくはみえるけど。
Avatar
受け取りはコントロールできないからなあ
Avatar
omochimetaru 5/15/2020 4:04 AM
僕は .toHoge(): Hoge つくってますね。
4:04 AM
でも標準ライブラリだとあんまりそれはなくって
Avatar
implicit ほしい
Avatar
omochimetaru 5/15/2020 4:04 AM
逆で、Hoge.init が T をうけとる
4:04 AM
APIが多いと思います
Avatar
なるほど、、
Avatar
omochimetaru 5/15/2020 4:04 AM
T.toHoge() じゃなくて Hoge.init(T)
Avatar
ふむー
4:05 AM
print() ってそういえばなんでも String にするけど
4:05 AM
どう言う理論なんだろう
Avatar
omochimetaru 5/15/2020 4:05 AM
printもそうですし "\(exp) これもそうですね
4:06 AM
結構やばい変換をいろいろやってますよ
Avatar
String() が実はめっちゃ強い
4:06 AM
とかじゃなく。
Avatar
omochimetaru 5/15/2020 4:06 AM
CustomStringConvertibleとかCustomDebugStringConvertibleとかStringOutputStreamとか (edited)
4:06 AM
いろいろなプロトコルに動的にダウンキャストしてます (edited)
Avatar
あー、なるほど
Avatar
omochimetaru 5/15/2020 4:07 AM
String(describing: Any) をつかってるんだったきがする
Avatar
String(describing:) なのか。
4:07 AM
/// A type with a customized textual representation. /// /// Types that conform to the `CustomStringConvertible` protocol can provide /// their own representation to be used when converting an instance to a /// string. The `String(describing:)` initializer is the preferred way to /// convert an instance of *any* type to a string. If the passed instance /// conforms to `CustomStringConvertible`, the `String(describing:)` /// initializer and the `print(_:)` function use the instance's custom /// `description` property.
4:07 AM
ほんとだ
4:08 AM
print(_:) は直接使ってるわけじゃないのかな?
Avatar
Kishikawa Katsumi 5/15/2020 11:31 AM
https://github.com/apple/swift-evolution/blob/master/proposals/0269-implicit-self-explicit-capture.md selfのキャプチャがシンプルになるやつ、次のSwiftに入るんですね。 値型にselfが要らなくなるのはよい、[self]は実際にはほとんど使わないかな?
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
11:33 AM
いや、UIView.animateとかの明らかに循環参照しないことを誰でも知ってるやつには使うと便利だな。
👍 1
Avatar
PromiseとかSingleだと循環気にしなくて良いので、結構 [self] 使いたいかも
Avatar
Kishikawa Katsumi 5/15/2020 11:44 AM
Promiseでも必要なときなかったでしたっけ?
Avatar
Promise自体を永続して保持し続けるような状況(あんまりやらないと思うけど)だと必要になりそうですね。
11:47 AM
非同期処理を上から下に順番に流す基本的な使い方のときは大丈夫
Avatar
Kishikawa Katsumi 5/15/2020 11:54 AM
extension Client { public func perform<Response>(request: Request<Response>) -> Future<Response, Error> where Response: Decodable { return Future<Response, Error> { [weak self] promise in self?.perform(request: request) { switch $0 { case .success(let response): promise(.success(response.body)) case .failure(let error): promise(.failure(error)) } } } } }
11:56 AM
^ こういうURLSessionのCompletionHandlerをFuture(Promise)にしてる実装があって、これはSinkする方で[weak self]しないとダメなんですけど呼び出される側の実装で回避できるかな?
11:57 AM
あ、これはそのさきのperformのCompletionHandlerをリトライのためにある程度保持するからかな?
11:58 AM
ちょっとまず自分でいろいろ確認してみます。
Avatar
これを見る限りはFutureが終われば解放されそうに見えますねえ
Avatar
Kishikawa Katsumi 5/15/2020 12:35 PM
それがこのコードを使う側は[weak self]にしないとViewControllerが解放されないんですよね。
Avatar
ふむ・・・
Avatar
Kishikawa Katsumi 5/15/2020 1:05 PM
import UIKit import Combine class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in let vc = ViewController2() self?.present(vc, animated: true) } } } class ViewController2: UIViewController { private var cancellables: Set<AnyCancellable> = [] deinit { print("deinit") } override func viewDidLoad() { super.viewDidLoad() Client.shared.perform(request: URLRequest(url: URL(string: "https://www.google.com")!)) .sink(receiveCompletion: { (completion) in print(completion) self.updateUI() }) { (response) in print(response) self.updateUI() } .store(in: &cancellables) } func updateUI() { } } class Client { static let shared = Client() private let session = URLSession(configuration: .default) private init() {} func perform(request: URLRequest) -> Future<URLResponse, Error> { return Future<URLResponse, Error> { [weak self] promise in self?.session.dataTask(with: request) { (data, response, error) in if let error = error { promise(.failure(error)) return } if let response = response { promise(.success(response)) return } } .resume() } } }
1:06 PM
^ 小さく再現できるコードだとこうなるんですけど、これはViewController2の self.updateUI() の呼び出しはweak selfじゃないとViewController2を閉じてもViewController2は解放されないんですよね。
Avatar
omochimetaru 5/15/2020 1:24 PM
このFutureは何度も開始できるObservableみたいな種類のものなのかな
1:25 PM
VC -> Set<AnyCancellable> -> Future -> VC のサイクルっぽい
Avatar
Kishikawa Katsumi 5/15/2020 1:27 PM
RxSwiftのSingleだとここはリークしないんですか?
1:27 PM
リーク=>循環参照
Avatar
Kishikawa Katsumi 5/15/2020 1:36 PM
しなかった。CombineのFutureとちょっと違うんですねえ。
1:40 PM
Futureも一度きりの動作に見えますね。
Avatar
omochimetaru 5/15/2020 1:41 PM
Futureが一度きりなら、クロージャ捨ててほしいけど、そうじゃないのか。
Avatar
Kishikawa Katsumi 5/15/2020 1:46 PM
RxSwiftのSingleだと[weak self]だとコールバックが返る前に画面を閉じるとselfがなくなるのでコールバックの中の処理はスキップできる、Strong参照している場合はコールバックが返るまでselfが保持されるので画面を先に閉じてもコールバックの処理が実行できる。
1:47 PM
Combineは後者の振る舞いは諦めるか、コールバックの中をselfを使わないようにする必要がある。 (edited)
1:47 PM
今のところこういう違いがあるのか。
Avatar
PromiseとかSingleだと循環気にしなくて良いので、結構 [self] 使いたいかも
こういうときでも VC が捨てられてから遅れて不要な処理が走るのが気持ち悪くて基本的に [weak self] + gurad let self = self else { return } してるなぁ。
Avatar
Kishikawa Katsumi 5/15/2020 1:56 PM
それは同意します。確認が大変なので全部[weak self]でお願いしたい、というのも含まれていますが。
1:57 PM
^ 画面を閉じてもしたい処理がある、というのはあまりないという前提で。
Avatar
omochimetaru 5/15/2020 1:58 PM
VCについてはweak captureして、disposeBagをdisposeさせてます。
1:58 PM
この話の例だと、僕がstrong selfにしたいのは、Clientのメソッドの方ですね
Avatar
確認が大変なので全部[weak self]でお願いしたい
これありますね。 weak ついてないときいちいち大丈夫か考えなきゃいけないし。
1:59 PM
guard let self = self else { return } がボイラープレートすぎて、 [weak self return] とかほしいです・・・。
Avatar
Kishikawa Katsumi 5/15/2020 1:59 PM
Clientの方はStrongにできるかなあ。例ではSingletonにしているけどClientも不要になったら解放したいので。 (edited)
2:01 PM
weak selfの場合をなんとかしたい、というのは先のProposalで触れられてるけど対象外だから別の提案でなんとかしよう、とか書いてあったと思います。
2:01 PM
要するに別に何も変わらない😅
😫 1
Avatar
async/await が入ったときに、 await 後は weak キャプチャしたい場合ってどうなるんだろう。
2:03 PM
基本循環しないから大丈夫ってことになるのかな。
Avatar
omochimetaru 5/15/2020 2:04 PM
awaitもそうですね、Promise相当だからstrong selfだらけ
2:05 PM
Clientも不要になったら解放したい
これが、VC.deinit -> DisposeBag.dispose -> Singleのterminateで、解放される。
🙏 1
Avatar
omochimetaru 5/15/2020 2:15 PM
明示的にweakにしたければ、weak var weakSelf = self ってかいておいてそれ使うしかない気がする。 (edited)
Avatar
await[weak self] とか。
2:22 PM
それができても、スコープが切られないからその後の gurad let self = self ... が許されなさそう・・・。 self が被って。 (edited)
2:23 PM
まあ strong で諦めることになるのかな。 await 後は self. 必須になるのかな?それならせめて await[self] はほしくなりそう。
Avatar
omochimetaru 5/15/2020 2:42 PM
await後はself不要のほうが自然なコードになって良いと思います
Avatar
self. 必須って意図しない strong capture を防ぐためのものだと思うけど、 await なら基本循環しない(解放される)から意図しない strong capture があっても問題ないってこと?
Avatar
omochimetaru 5/15/2020 3:11 PM
はい。
3:11 PM
でも、deinitでキャンセルとかの仕組みと噛み合わない事はありそうですねえ。 (edited)
Avatar
そもそも await の後ろはクロージャじゃなくて self のメソッドそのものだから、 self が解放されてるのはおかしいか。
Avatar
omochimetaru 5/15/2020 3:43 PM
あ~、たしかに。
Avatar
Kishikawa Katsumi 5/15/2020 3:46 PM
awaitの下はコールバックの中だからselfが解放されていることはあるんじゃないですか?
Avatar
omochimetaru 5/15/2020 3:47 PM
async func がメソッドだった場合、
3:47 PM
メソッドの呼び出し中はselfがretainされているという規則があるから (edited)
3:47 PM
それの延長で考えるとってことです
Avatar
Kishikawa Katsumi 5/15/2020 3:47 PM
あ、そういうルールがあるんですね。
3:47 PM
違うか、
Avatar
omochimetaru 5/15/2020 3:47 PM
ObjCのARCだとなかったんだけどSwiftだとある。 (edited)
Avatar
Kishikawa Katsumi 5/15/2020 3:48 PM
awaitがあってもなくても
3:48 PM
メソッドの途中でselfが消えることはない、ってことですね。
3:49 PM
一般的な言語仕様として。
Avatar
omochimetaru 5/15/2020 4:00 PM
はい
Avatar
view controller はかなり簡単にleakするので、
4:13 PM
weak を意図的に強制してるかつ debug では leak detection するロジックをいれてる (edited)
Avatar
こういうときでも VC が捨てられてから遅れて不要な処理が走るのが気持ち悪くて
Avatar
Kishikawa Katsumi 5/15/2020 4:27 PM
なるほど。全部weak書いてるつもりでもコールバックがネストしたら循環参照したりしたことがあったので、さらに検知する機構が入ってるのはいいですね。
Avatar
かなりアレな実装だけど。view controllerのポインタ定期的にしらべて画面にでてるかどうかチェックという... (edited)
4:28 PM
でもVCがリークするのはほんとうに頻繁にあるので役には立っている。
4:28 PM
UIKitの仕組み上、VCはめっちゃ大量の所有をしているので一つのリークのインパクトがでかい (edited)
Avatar
コールバックがネストしたら循環参照したり
ネストする場合も各段階で毎回 [weak self] してますね。ネストで循環参照したのはどこかの段階で [weak self] を忘れた場合ということですか?
4:34 PM
それとも全部書いても循環参照するパターンということですか?
Avatar
Kishikawa Katsumi 5/15/2020 4:38 PM
全部書く、でOKなんですけど、どっちかではself使ってないみたいなときに書き忘れることがあったり
Avatar
機械的に検出できるといいですよね。一応、どこかで書き忘れても self. を書かなければ大丈夫だと思うんで、 self. を書くときにキャプチャしようとしてると気付くかなと思いながら書いてます。
Avatar
@swift-5.2.5 let range = 0 ... 10 print(range.startIndex < 0)
Avatar
exit status: 1 with stderr:<stdin>:2:24: error: referencing operator function '<' on 'BinaryInteger' requires that 'ClosedRange<Int>.Index' conform to 'BinaryInteger' print(range.startIndex < 0) ^ Swift.BinaryInteger:1:11: note: where 'Self' = 'ClosedRange<Int>.Index' extension BinaryInteger { ^
Avatar
@swift-5.2.5 let range = 0 ..< 10 print(range.startIndex < 0)
Avatar
false
Avatar
この ClosedRange の挙動は仕様?
10:42 AM
なんかダメなケースがあった気が。
Avatar
RangeとClosedRangeで違うのか。なんでだろう。
10:43 AM
いずれにしても、 .startIndex を Int と比較するのがそもそも変な感じはします。
Avatar
Range<Int>IndexInt じゃない?
10:44 AM
Array ならできるわけで。
Avatar
Range<Int>.subscriptRange<Int>.Index を渡した結果の型は Int だと思うけど
10:45 AM
Range<Int>.Index 自体が Int である必要性はない
10:45 AM
性質的に Int でも全く問題ないですけど。
Avatar
うーーん、どっちが良いとも言いづらいな。
10:47 AM
< については lowerBound と比較すればいいんだけど、 RangeClosedRange の違いは気になる・・・。
10:49 AM
あと関係ないけど、 lowerBoundlet であるのは、おもち理論↓的に必要なさそう? https://qiita.com/omochimetaru/items/7265e440418b38088ccb
記事について この記事は potatotips#39 という勉強会で発表した内容を再掲したものです。スライドの画像と、喋った言葉を載せました。 以下スライド それではこれから、Swift の struct の st...
Avatar
あ、lowerBoundは微妙ですね
10:51 AM
lowerBound <= upperBound という恒等式を満たさないといけないから
10:51 AM
lowerBound 単体で変更できるのはまずい
Avatar
willSetprecondition かけたらどうだろう?
Avatar
それはありかも。
10:54 AM
まあ、didSetでもいいです。
Avatar
CoreTeam的には、基本的に制約があるプロパティは struct でも let の方針なのかな。
Avatar
どうだろう。他にどんな型があるかな・・・
Avatar
わからないけど、 lower/upperBoundlet だったのが、さっき見つけて理解できるけど、そうなのかーと思ったので。
Avatar
初歩的な質問で申し訳ないのですがSwiftでDiscord botを作成することってできますか?
Avatar
できますよ
12:01 PM
Discord library for Swift. Contribute to Azoy/Sword development by creating an account on GitHub.
12:01 PM
僕が作ってみたときはこれ使いました
12:01 PM
Discord API Client for Swift. Contribute to nuclearace/SwiftDiscord development by creating an account on GitHub.
12:01 PM
こっちもある
Avatar
ありがとうございます!今までdiscord.jsでしか作ったことがなくて、作って観れるのかなと思い 早速作ってみます
Avatar
Swift Compiler Discordapp Bot. Contribute to norio-nomura/SwiftCompilerDiscordappBot development by creating an account on GitHub.
12:06 PM
nomuraさんが作ってるこのサーバにいるswiftコンパイルbotのコード↑ これもSwift製です (edited)
Avatar
ありがとうございます!
Avatar
ボットのホスティング環境のおすすめはございますか (edited)
Avatar
omochimetaru 5/19/2020 2:02 AM
Swift on Linuxならなんでも良さそう
Avatar
了解です ありがとうございます
Avatar
omochimetaru 5/21/2020 8:00 AM
The Swift to Kotlin translator. Contribute to vinivendra/Gryphon development by creating an account on GitHub.
8:06 AM
Swift to Kotlin translatorらしい。 Arrayが壊れまくりそう https://vinivendra.github.io/Gryphon/collections.html
The Swift to Kotlin translator.
Avatar
https://discordapp.com/channels/291054398077927425/291054454793306112/702188269319880784 これ変更されて、複数行に渡るときは let に対してインデントするようになります。
9:43 PM
https://github.com/apple/swift/pull/31941 let files = try some(at: nil) .filter { return ... }.map { ... }
Don&#39;t column align PBD entries if any entry spans from the same line as the var/let to another line. For example: // Previous behavior: let foo = someItem .getValue(), // Column-align...
💪 1
Avatar
.mapそこなのかあ
Avatar
.map の位置は書き手次第ですよ。
Avatar
なるほど
Avatar
次行に書いた場合は let files = try some(at: nil) .filter { return ... } .map { ... }
Avatar
このほうが最初の行と統一感があっていい
Avatar
Kishikawa Katsumi 5/22/2020 1:43 AM
おお、ということはCombineのstore()も同じ位置になりますか? NotificationCenter.default.publisher(for: UIApplication.keyboardWillChangeFrameNotification) .receive(on: RunLoop.main) .sink { [weak self] in self?.keyboardWillChangeFrame($0) } .store(in: &cancellables) 今までは } .store だけ手作業でインデントを直してました。
Avatar
はい、意図通りのインデントになると思います。
👏 3
Avatar
Kishikawa Katsumi 5/22/2020 1:57 AM
やったー。ありがとうございます。
❤️ 1
Avatar
めっちゃいい
Avatar
なんでやろう・・・UI調整してるときに,適当なコード書いたら,こんなコードで型推論が失敗した.
10:14 AM
10:15 AM
項が多いと,コケちゃうのかしら.
Avatar
Kishikawa Katsumi 6/8/2020 10:15 AM
Floatとリテラルを混ぜると起こりがちな気がする
Avatar
omochimetaru 6/8/2020 10:15 AM
リテラルの足し算とか掛け算はめっちゃそうですね
Avatar
そうなのかw
10:16 AM
height = self.view.safeAreaInsets.top + CGFloat(44 + 10 + 44 + 10 + 10)
10:16 AM
とりあえず,これで回避した.
Avatar
Kishikawa Katsumi 6/8/2020 10:17 AM
いい感じ。
Avatar
omochimetaru 6/8/2020 10:17 AM
項の数で指数的に推論が重くなる
Avatar
Kishikawa Katsumi 6/8/2020 10:17 AM
いい感じだけど、その足し算気になりますね。それ必要かな。SwiftUIだとしかたない気もするけど。
Avatar
一番手っ取り早い方法だと型アノテーションだけつければ良くなる気が (edited)
10:18 AM
あ、、
Avatar
あ,調整中というか,雰囲気を調べるために高さとマージンを手で書いてました
Avatar
すでにある変数への代入か、しつれいしましたmm (edited)
👍 1
Avatar
Kishikawa Katsumi 6/8/2020 10:18 AM
なるほど。納得です🙏
Avatar
実際のときは,ちゃんと定数とかに置き直して,綺麗に書く予定
10:20 AM
いや,こんなところで型推論失敗しないと思い込んでて,コンパイルは長いわ,コンパイルが失敗してる理由を探し当てるのに四苦八苦しました.
Avatar
omochimetaru 6/8/2020 10:20 AM
失敗するんですよねぇ
Avatar
https://qiita.com/freddi_/items/044bdf6defbbe434a8e2#comment-2fc63d4d19f07e8fc5e4 この記事のおもちさんのコメントを思い出した (edited)
こんにちは、freddiと申します。Swiftを始めて8ヶ月少々、最近は周囲の影響からかSwiftコンパイラやSILについてちょっと勉強し始めています。 この記事は、「Swift Advent Calendar 2018」の14日目...
Avatar
まぁそうか,選択肢が3つあって,リテラルが5個あったら,3^5の選択肢が・・・・・
Avatar
omochimetaru 6/8/2020 10:23 AM
そんな感じ
Avatar
試してないんですけど、リテラルがFloatだったら大人しくなりそう? ... + 44.0 + 20.0 + 56.0 みたいな
Avatar
行けそうな気がする
10:31 AM
ko
10:31 AM
こけた
10:31 AM
10:32 AM
正直,CGFloatかましても,結構遅い
10:34 AM
if self.traitCollection.horizontalSizeClass == .regular { height = self.view.safeAreaInsets.top + CGFloat(44) + CGFloat(10) + CGFloat(10) } else { if self.view.bounds.size.width < self.view.bounds.size.height { height = self.view.safeAreaInsets.top + CGFloat(44) + CGFloat(10) + CGFloat(44) + CGFloat(10) + CGFloat(10) } else { height = self.view.safeAreaInsets.top + CGFloat(44) + CGFloat(10) + CGFloat(10) } }
10:34 AM
こうしたら,爆速になった
10:34 AM
めんどい
Avatar
omochimetaru 6/8/2020 10:35 AM
F()みたいに1文字の関数を用意するとか?
Avatar
もう1個回避方法見つけた
10:37 AM
Intへの暗黙を狙うパターン
10:37 AM
let tmp = 44 + 10 + 44 + 10 + 10 height = self.view.safeAreaInsets.top + CGFloat(tmp)
10:37 AM
どちらにしても余計だけど,これが一番,理想に近い.
Avatar
omochimetaru 6/8/2020 10:38 AM
let tmp: CGFloatでもいけますか? (edited)
Avatar
いけた
Avatar
あ〜 CGFloatが確かくせ者で
10:47 AM
これとリテラルを混ぜるとすぐコケるだった気がしてきた
Avatar
CGFloatは32-bit/64-bitでもアレなとてもアレな型
6:38 PM
ところで44dp足すのはいろいろダメな気がする
Avatar
それはそうw
Avatar
リテラルの型推論の上で FloatCGFloat に何か違いってありますか?↑の CGFloat が仮にすべて Float だったとしても同じことが起こりそうに思うんですが( import CoreGraphics した( ExpressibleByFloatLiteral に適合した型が同じ数だけある)状態では)。
11:24 PM
Double は優先ルールがあるから違いがあるかもしれないけど。
Avatar
omochimetaru 6/8/2020 11:25 PM
FloatとCGFloatは同じはず
Avatar
だよね。
Avatar
omochimetaru 6/8/2020 11:25 PM
Doubleだけが特別
Avatar
ExpressibleByFloatLiteral に適合した型、 Double, Float, CGFloat だけじゃなく、たくさんあるっぽい。 Decimal DispatchQueue.SchedulerTimeType.Stride ImmediateScheduler.SchedulerTimeType.Stride MaterialScalarParameter NSDecimalNumber NSNumber OperationQueue.SchedulerTimeType.Stride RunLoop.SchedulerTimeType.Stride https://developer.apple.com/documentation/swift/expressiblebyfloatliteral
11:26 PM
これに加えて BinaryFloatingPoint
Avatar
omochimetaru 6/8/2020 11:27 PM
多分探索されるのは適合してる型じゃなくって
11:27 PM
足し算のオーバーロードの方です
Avatar
リテラルの組み合わせも考えてるんじゃないの?
Avatar
omochimetaru 6/8/2020 11:28 PM
いや、考えない感じがする 見落としがなければ。
11:30 PM
言い方を変えると、Decimalとして推論されるためには、多項式の中にDecimalが確定してる項がないといけない。
11:30 PM
あ、Decimalはオーバーロードがあるかな?
Avatar
DecimalSignedNumeric らしいからあるみたい。
11:32 PM
Stride 系も Numeric に適合してるね。
Avatar
omochimetaru 6/8/2020 11:32 PM
import なし (edited)
Avatar
あー、しかも今リテラルは整数リテラル書いてるから、もっと数があるのか。
Avatar
omochimetaru 6/8/2020 11:33 PM
import Foundation (edited)
Avatar
+ を持つ整数リテラルで記述できる型って山のようにあるよね。
Avatar
omochimetaru 6/8/2020 11:34 PM
Decimalの+はあるけど
11:35 PM
NSNumberの+は無いですね (edited)
Avatar
うん、NSNumber はない。
11:35 PM
けど Stride 系はあるっぽい。
Avatar
omochimetaru 6/8/2020 11:35 PM
FloatingPointの+で済ませるんだと思う。
11:35 PM
プロトコルの+de
Avatar
ん? NSNumber+ できないんじゃないの?
Avatar
omochimetaru 6/8/2020 11:36 PM
アレ、本当だ
Avatar
@swift-5.2.5 import Foundation let a: NSNumber = 2 let b: NSNumber = 3 print(a + b)
Avatar
exit status: 1 with stderr:<stdin>:4:9: error: binary operator '+' cannot be applied to two 'NSNumber' operands print(a + b) ~ ^ ~ <stdin>:4:9: note: overloads for '+' exist with these partially matching parameter lists: (Array<Element>, Array<Element>), (CGFloat, CGFloat), (Date, TimeInterval), (Decimal, Decimal), (DispatchTime, DispatchTimeInterval), (DispatchTime, Double), (DispatchWallTime, DispatchTimeInterval), (DispatchWallTime, Double), (Double, Double), (Float, Float), (Float80, Float80), (IndexPath, IndexPath), (Int, Int), (Int16, Int16), (Int32, Int32), (Int64, Int64), (Int8, Int8), (Measurement<UnitType>, Measurement<UnitType>), (Other, Self), (Self, Other), (Self, Self.Scalar), (Self, Self.Stride), (Self.Scalar, Self), (Self.Stride, Self), (String, String), (UInt, UInt), (UInt16, UInt16), (UInt32, UInt32), (UInt64, UInt64), (UInt8, UInt8) print(a + b) ^
Avatar
omochimetaru 6/8/2020 11:36 PM
ExpressibleByFloatLiteral じゃないのか? (edited)
Avatar
いや、 ExpressibleByFloatLiteral ではあるはず。
11:38 PM
@swift-5.2.5 import Foundation let a: NSNumber = 2.0 print(a)
Avatar
2.0
Avatar
AddtiveArithmetic ではない。
Avatar
omochimetaru 6/8/2020 11:38 PM
うひー FloatingPointでもAdditiveArithmeticでもねえのかw
11:39 PM
例が悪かった。
Avatar
まあ、↓とか考えると・・・。 @swift-5.2.5 import Foundation let a: NSNumber = 2.0 let b: NSNumber = true print(a + b)
Avatar
exit status: 1 with stderr:<stdin>:4:9: error: binary operator '+' cannot be applied to two 'NSNumber' operands print(a + b) ~ ^ ~ <stdin>:4:9: note: overloads for '+' exist with these partially matching parameter lists: (Array<Element>, Array<Element>), (CGFloat, CGFloat), (Date, TimeInterval), (Decimal, Decimal), (DispatchTime, DispatchTimeInterval), (DispatchTime, Double), (DispatchWallTime, DispatchTimeInterval), (DispatchWallTime, Double), (Double, Double), (Float, Float), (Float80, Float80), (IndexPath, IndexPath), (Int, Int), (Int16, Int16), (Int32, Int32), (Int64, Int64), (Int8, Int8), (Measurement<UnitType>, Measurement<UnitType>), (Other, Self), (Self, Other), (Self, Self.Scalar), (Self, Self.Stride), (Self.Scalar, Self), (Self.Stride, Self), (String, String), (UInt, UInt), (UInt16, UInt16), (UInt32, UInt32), (UInt64, UInt64), (UInt8, UInt8) print(a + b) ^
Avatar
omochimetaru 6/8/2020 11:39 PM
足し算できるけど、足し算の直接定義がなくて、プロトコル定義での足し算に頼ってる型を探してた
Avatar
+ ってオペランドの型が Self だからそんなことある?
Avatar
omochimetaru 6/8/2020 11:40 PM
Swift.(file).FloatingPoint.+, が出てくるから。 (edited)
Avatar
↓の中にはなさそう? <stdin>:4:9: note: overloads for '+' exist with these partially matching parameter lists: (Array<Element>, Array<Element>), (CGFloat, CGFloat), (Date, TimeInterval), (Decimal, Decimal), (DispatchTime, DispatchTimeInterval), (DispatchTime, Double), (DispatchWallTime, DispatchTimeInterval), (DispatchWallTime, Double), (Double, Double), (Float, Float), (Float80, Float80), (IndexPath, IndexPath), (Int, Int), (Int16, Int16), (Int32, Int32), (Int64, Int64), (Int8, Int8), (Measurement<UnitType>, Measurement<UnitType>), (Other, Self), (Self, Other), (Self, Self.Scalar), (Self, Self.Stride), (Self.Scalar, Self), (Self.Stride, Self), (String, String), (UInt, UInt), (UInt16, UInt16), (UInt32, UInt32), (UInt64, UInt64), (UInt8, UInt8)
11:44 PM
あ、 NSNumberFloatingPoint じゃないからか。 (edited)
Avatar
omochimetaru 6/8/2020 11:49 PM
FloatingPoint.+は実装は無いっぽい
11:53 PM
11:54 PM
RangeReplaceableCollection.+は、protocol extensionとして実装が与えられているから
11:54 PM
もし、ExpressibleByFloatingLiteralで、かつ、RangeReplaceableCollectionな型を自作した場合は、
11:54 PM
これは足し算の項のどこかにその型が無いと推論できないはず
Avatar
dangomushi.3 6/10/2020 8:02 AM
今、iPadを制御するためのBluetoothのマウスの作成をしています。 そこで、以下の点をご存じの方がいればおしえてもらえますか。 ・マウスカーソル位置をピクセル単位で指定できるか
Avatar
ソフトウェアから位置をずらすということかな...?
4:21 PM
HIDとして特定の位置に移動するということかな...?
Avatar
dangomushi.3 6/10/2020 9:55 PM
できれば後者の、特定の位置へポインタを移動させることがしたいと思っています。 macOS用であればNSViewControllerを使えば任意の位置にマウスポインタを移動できたので、同様のことをiPadOSやiPhoneでも実装したいと考えています。
Avatar
たぶん正攻法ではそういうことはできなくて
💯 1
11:34 PM
ひょっとすると UIAccessibility 関連でできるかもしれない、くらいですかねえ印象としては。
Avatar
なるほど。 現時点でマウスデバイスとしては認識できているんですが、どうもピクセル位置を直接指定した制御だけはできないみたいで、何か方法があればと思っていたのですが難しそうですね。 UIAccessibility関連について再度調査してみます。ありがとうございます。
Avatar
dangomushi.3 6/11/2020 1:16 AM
ちなみに、特定の位置に移動するのではなく、指定した量だけマウスポインタを動かすということはできると思いますか? (ポインタの位置を直接指定できないとなるとこちらも難しいとはおもいますが)
Avatar
このけんちょっと考えましたが可能性としては、UIWindowsendEvent:あたりでUIEventを奪って、(UIHoverEventが pointer とかのやつっぽい)加工すれば可能なような気がしています。 (edited)
4:44 PM
どの方法でもprivate apiへのアクセスは必要そうですね (edited)
Avatar
dangomushi.3 6/16/2020 4:23 AM
いろいろと考えていただきありがとうございます。 挑戦してみます!
Avatar
質問です
4:51 PM
あ、ここじゃないほうがいいかな。
4:51 PM
#swiftpm かも
Avatar
中身によるのでは
Avatar
SPMの話だからそっち行きます〜
Avatar
The result changes when you import Foundation. ("\r\n").contains("\r") // false ("\r\n").contains("\n") // false But: import Foundation ("\r\n").contains("\r") // true ("\r\n").contains("\n") // true (Tested in Xcode 11.5.1, Swift 5.2.4) This is because String implic...
Avatar
マジかww
12:46 AM
import Foundation changes many things for sure
Avatar
Xcodeのインデントの話題が最近あった気がするんだけれど、どこだっけ...
4:22 AM
Don&#39;t column align PBD entries if any entry spans from the same line as the var/let to another line. For example: // Previous behavior: let foo = someItem .getValue(), // Column-align...
Avatar
Kishikawa Katsumi 6/19/2020 2:28 AM
標準ライブラリをモジュールに分けて必要なものだけ、とするとそういう場合だいたい外したいのはStringとかLocaleとかだったりすると仮定すると、どのライブラリを利用しているかでソートの結果とかも変わってしまう、みたいなことになるのかな。
2:30 AM
みたいなことを考えると、最適化でがんばって枝を払う方が良い結果になるのかもしれない。
Avatar
最適化でがんばって十分な効果が出るなら、コードを書くときに人間ががんばらなくていいので良いと思います。僕は今の標準ライブラリの範囲はひとかたまりとして好きですね。
2:39 AM
Java みたいにコレクション使うためにインポート、とかは嫌な感じが。
2:41 AM
I/O とかネットワークとか入ってなくて、(本来の意味の)スクリプト言語として他のプログラムに埋め込む用途にもちょうど良い範囲になっているように思います。
2:42 AM
SIMD はちょっと異質でしたが・・・。
Avatar
Kishikawa Katsumi 6/19/2020 2:46 AM
それはそんな気がしますね。良いバランスなのかも。
2:46 AM
ファイルIOが入ってないなら文字列の扱いは入出力だから(標準ではない)ライブラリでやるべき、とも思うけどそこは実用性とのバランスかなあ。
Avatar
さすがに String が標準外なのは辛いし、内部でいい感じに ASCII か Unicode かとか考慮して切り替えてくれて、 ASCII の範囲でしか使ってないときは Unicode 側には触らず、最適化で消えてくれるとかが理想的な気がしますね。
Avatar
Kishikawa Katsumi 6/19/2020 2:52 AM
ASCIIの範囲だったら、ってさすがにコンパイラ・リンカがわかるケースはすごく限られるから人間がヒントを与える仕組みも必要かも。
Avatar
内部で String の実体となる型を分けて、リテラルから ASCII のみのときは ASCII 限定の実体に紐付けられて、 ASCII 限定の実体の API しか呼び出されてないから他は消される、とかはきついかな・・・。 (edited)
Avatar
Kishikawa Katsumi 6/19/2020 3:02 AM
最適化でうまくやってくれる、ということになったら標準ライブラリはもっと拡充しやすくなるのかな。 Linked ListやOrdered Setはよく言われるけどそういうのも入れてしまって良いという判断にしやすいかも。
Avatar
そもそも String の仕様が...
3:04 AM
なんというか顧客が本当に必要だったものではないというか...
Avatar
omochimetaru 6/19/2020 3:07 AM
String(data: data, encoding: .utf8) とかすぐ出てくるのでこの時点で膨大なunicode仕様が必要になっちゃいますね
3:07 AM
↑のencoding:.ascii だったらカットできるけど。
Avatar
omochimetaru 6/19/2020 3:16 AM
顧客が本当に必要だったものではない
よくバグってるのは別として、仕様自体は、やっと正しいものにたどり着いたと思ってます、僕は。
Avatar
Kishikawa Katsumi 6/19/2020 3:16 AM
Stringの仕様はどうなってるのがいいんでしょうねえ。 私はRubyのがいいんじゃないかと思ってます。
3:17 AM
いや、それも大変かな。
Avatar
omochimetaru 6/19/2020 3:17 AM
UTF-8みたいな可変長シーケンスは、いきなり飛び地への効率的なシークができないので、indexの仕様を普通の配列みたいにするとよくない。 (edited)
3:18 AM
UTF-16にしてそれができる処理系もあるけど、結局はサロゲートペアでつらいことになるわけで(最近は絵文字合成もよくあるし)、あれも嘘だし。 (edited)
Avatar
Kishikawa Katsumi 6/19/2020 3:22 AM
逆か、UTF-8に依存しない自由なStringを用意すればいいのか。
3:23 AM
内部エンコーディングにUTF-8を使うというのはたぶん99%くらいはそれでうまくいくわけだから。
Avatar
UTF-8として読み込むときに一度なめるんだったら、そのときにインデッスクテーブル作って内部に保持しておけばインデックスでランダムアクセスできると思うんだけど、Stringが太るのは許容できない?
Avatar
omochimetaru 6/19/2020 4:04 AM
それはString型じゃなくてそういうデータ構造の二次的な型を作るのが良いと思います
4:05 AM
そうすればString直接使う場合と、そのテーブル付きStringを使う場合の両方選択できて、トレードオフをユーザが決定できる。
4:05 AM
そもそも、ランダムアクセスが必要なシチュエーションがどういうものかも、気になりますけど。
4:07 AM
例えばパーサーのバックトラックだったら、戻りたいところだけindexを事前に保存しておけるし、行頭の逆方向への検索も逐次的な移動でできるし、一定文字数で丸めるとかもできるし・・・
4:08 AM
クロスワードパズルゲームを実装するみたいなちょっと変わったシナリオでしかインデックスランダムアクセスは必要ない気がします。
4:08 AM
(ただクロスワードの例だったら文字列長が短いので毎回頭から数え上げても大丈夫そうだ)
4:13 AM
どちらかというと、みんなが気に食わないのって、
4:13 AM
stringとindexのデータ構造のほうじゃなくって
4:14 AM
str[str.index(str.startIndex, offsetBy: 2)] って、 str を3回書かないといけないところじゃないかと思います。
4:16 AM
これについては https://forums.swift.org/t/offset-indexing-and-slicing/28333 これが進んだら解決すると思ってて
v2 changes Removed .start and .end, now all OffsetBounds are built from .first and .last. Simplifies usage and learnability. Delineates OffsetBound abstraction and terminology from indices. Added RangeReplaceableCollection convenience overloads, subscript setters. .inser...
4:17 AM
str[.first + 2] って書けるようになります。
Avatar
うーん、現実的にでもなんかcharacter単位で操作してうれしいことがあんまりないっていうか... (edited)
4:25 AM
ほとんどの操作はscalarかUTF-16単位だったり。
4:26 AM
Swiftがどう、というより、Swiftが生きている世界がSwiftの世界と違いすぎて、
4:26 AM
(e.g. JVMベースのデータサービス、Objective-CのUIライブラリなど) (edited)
4:27 AM
NSString的なのがほとんどでString的な操作は例外という印象
4:29 AM
そして多分その未来は当分変わらない
Avatar
omochimetaru 6/19/2020 5:06 AM
scalar単位の操作に関しては .unicodeScalars が使えるので、 デフォルトのcollectionがcharacters相当なのがめんどくさいって意味ですかね?
5:07 AM
そして多分その未来は当分変わらない
NSStringとかを使い倒す必要があってcharactersとして使う場面が少ないというのは課題だと思います、↑のmichaelさんもStringサポート拡充担当なはず
5:08 AM
とりあえず正規表現とか進んでほしい
Avatar
そう
6:22 AM
デフォルトがUnicode Code Pointの操作で、拡張で UTF-16/UTF-8、さらにオプショナルな拡張で Grapheme の操作でよかった。 (edited)
6:23 AM
ああ、未来が変わらないのは取り巻く環境がってことね
6:23 AM
世の中のStringは多分そうとう先までUTF-16だと思う。
Avatar
omochimetaru 6/19/2020 6:33 AM
デフォルトがコードポイントなるほど・・・ (edited)
6:33 AM
確かに他の言語がだいぶどうにもならなそうですね>世の中
Avatar
そしてswiftがそれ単体でシステムを作る世界は多分こないので
6:34 AM
結局swiftのstringがデフォルトでcharacter操作で嬉しいってことはなかったという (edited)
6:34 AM
そんな感じ
Avatar
omochimetaru 6/19/2020 6:35 AM
逆に言えばSwiftが10年後に戦える言語で居られるかもしれない
Avatar
Apple「新しい言語つくりました、 Swiftはもうだめです」 (edited)
6:35 AM
ありうるんだよなあ
Avatar
omochimetaru 6/19/2020 6:36 AM
そうですねえw
Avatar
↓ってダメなんでしたっけ? @swift-5.2.5 protocol P1 { func foo() -> Int } protocol P2: P1 { func bar() -> String } class C1 { init<P: P1>(_ p: P) {} } class C2: C1 { override init<P: P2>(_ p: P) { super.init(p) } }
Avatar
exit status: 1 with stderr:<stdin>:14:14: error: overridden method 'init' has generic signature <P where P : P2> which is incompatible with base method's generic signature <P where P : P1>; expected generic signature to be <P where P : P1> override init<P: P2>(_ p: P) { ^ <stdin>:10:5: note: overridden declaration is here init<P: P1>(_ p: P) {} ^
Avatar
C2C1 としたときに init ができなくてダメ? (edited)
6:59 AM
C1.initrequired じゃないときに問題ありますか?
Avatar
omochimetaru 6/19/2020 7:15 AM
struct S1: P1 {} (C2.self as C1.Type).init(S1()) これで破綻しそう (edited)
7:16 AM
でもそもそもジェネリックシグネチャを縮めたりしながらオーバライドするのできましたっけ
7:17 AM
その型パラメータのvariancityを判定しないといけないから難しい気がするけど。
Avatar
@omochimetaru required じゃないとそもそも↓ができないみたいで @swift-5.2.5 class C { init() {} } let cType = C.self print(cType.init())
Avatar
exit status: 1 with stderr:<stdin>:6:13: error: constructing an object of class type 'C' with a metatype value must use a 'required' initializer print(cType.init()) ~~~~~ ^ <stdin>:2:5: note: selected non-required initializer 'init()' init() {} ^
Avatar
@swift-5.2.5 class C { required init() {} } let cType = C.self print(cType.init())
Avatar
main.C
Avatar
それならダメな理由あるかなと。
Avatar
omochimetaru 6/19/2020 7:32 AM
requiredじゃない場合、サブクラスにもそのinitがあるとは限らないのか。
7:33 AM
じゃあrequiredじゃないinitをoverrideする意味ってなんだろう overrideするとsuper.initが呼べるぐらいの意味しかないのかな。 (edited)
7:33 AM
struct S1: P1 {} (C2.self as C1.Type).init(S1()) だめな理由はこれが型としておかしくなるからってのもあるけど、 そもそもジェネリックシグネチャを縮めたりしながらオーバライドするのできましたっけ
Avatar
Overridden method 'init' has generic signature <A where A : Sequence> which is incompatible with base method's generic signature <A>; expected generic signature to be <A> ダメみたいですね
8:12 AM
こっちだと通る。これ目的で余計な型パラ追加したの1回だけあった気がするな class Foo<A> { init(a: A) { } } class Bar<A>: Foo<A> where A: Sequence { override init(a: A) { super.init(a: a) } }
Avatar
omochimetaru 6/19/2020 8:13 AM
ダメな方の入力はどんなコード?
Avatar
class Foo { init<A>(a: A) { } } class Bar: Foo { override init<A: Sequence>(a: A) { super.init(a: a) } } (edited)
Avatar
omochimetaru 6/19/2020 8:15 AM
protocol P1 {} protocol P2 : P1 {} class Animal { func f<X: P2>(_ x: X) {} } class Cat: Animal { override func f<X: P1>(_ x: X) {} }
8:15 AM
↑これいけた。
Avatar
おー
8:15 AM
Anyだけだめなのか
Avatar
omochimetaru 6/19/2020 8:15 AM
いや、ちがう
8:15 AM
variance逆
Avatar
あw
Avatar
omochimetaru 6/19/2020 8:16 AM
引数で使ってる型はcontravarianceだから継承先では広がらないといけない
Avatar
そもそもinit引数だから大分変なことやってたわ
Avatar
omochimetaru 6/19/2020 8:17 AM
protocol P1 {} protocol P2 : P1 {} class Animal { func g<X: P1>() -> X { fatalError() } } class Cat: Animal { override func g<X: P2>() -> X { fatalError() } // Overridden method 'g' has generic signature <X where X : P2> which is incompatible with base method's generic signature <X where X : P1>; expected generic signature to be <X where X : P1> }
8:17 AM
covarianceはダメだった
Avatar
普通のメソッドや static method でそうなるのはいいとして、 .init で呼び出せない required でない init の場合はどういう問題があるの?
Avatar
シンプルにrequiredじゃないinitはサブタイプではoverrideしない限り存在しないことになってるので
Avatar
omochimetaru 6/19/2020 8:20 AM
あれ?さっきの変な気がしてきた
8:26 AM
class Animal { init<X: P2>(_ x: X) { } } class Cat: Animal { override init<X: P1>(_ x: X) { super.init(S2()) } }
8:26 AM
これはコンパイルできますね。
8:29 AM
どういう問題があるの?
そもそもoverrideとして型がおかしいからoverrideできない、というレベルのエラーに思えます。
8:30 AM
ただこのoverrideって別に動的ディスパッチされる事がなさそうだから、実際には型がめちゃくちゃでも問題は無いのかな?その場合overrideじゃなくて単に同名の無関係なinitがあるって事ですけど。
8:34 AM
あ、わかったかも・・・?
Avatar
@swift-5.2.5 class C1 { init(_ x: Int) {} } class C2: C1 { init(_ x: String) { super.init(42) } }
Avatar
no output
Avatar
↑これができるのに
8:35 AM
@swift-5.2.5 protocol P {} protocol Q {} extension Int: P {} class C1 { init<T: P>(_ x: T) {} } class C2: C1 { init<T: Q>(_ x: T) { super.init(42) } }
Avatar
exit status: 1 with stderr:<stdin>:10:5: error: overridden method 'init' has generic signature <T where T : Q> which is incompatible with base method's generic signature <T where T : P>; expected generic signature to be <T where T : P> init<T: Q>(_ x: T) { ^ <stdin>:6:5: note: overridden declaration is here init<T: P>(_ x: T) {} ^
Avatar
↑これができないのが問題な気がする。
Avatar
omochimetaru 6/19/2020 8:36 AM
(連続した投稿が混ざっちゃったので再投稿) こういうことだ。 class Animal { init<X: P2>(_ x: X) { } required convenience init() { self.init(S2()) } } class Cat: Animal { override init<X: P1>(_ x: X) { super.init(S2()) } } func main(_ animalType: Animal.Type) { animalType.init() } main(Cat.self) convenience required initからinitを呼び出したときに動的ディスパッチです。 (edited)
Avatar
??これは required だからそうじゃないの? required がついてないときに引数の型を狭めるのが許可されないのはなぜ?という話では? (edited)
Avatar
omochimetaru 6/19/2020 8:39 AM
required convenience init は関係なくて、
Avatar
あれ?見間違いか? init は引数があるのか。
Avatar
omochimetaru 6/19/2020 8:40 AM
initとoverride initの間で、型パラメータがcontravarianceでないといけないよという話です。
8:40 AM
required convenience initが出てきたのは、
.init で呼び出せない required でない init の場合はどういう問題があるの?
これにたいする回答です。
8:41 AM
<metatype>.init で呼び出すことはできないけど、 別のinitからself.init で呼び出すことはできるので、
8:41 AM
そこで動的ディスパッチが発生するので、関数型の互換性を保ってオーバライドされてないといけない。 (edited)
Avatar
えっと、そもそもオーバーライドしろって言われるのが変な気がして、オーバーライドせずに↓を通すのはダメなんだっけ?ジェネリックだとシグネチャが被る? protocol P {} protocol Q {} extension Int: P {} class C1 { init<T: P>(_ x: T) {} } class C2: C1 { init<T: Q>(_ x: T) { super.init(42) } }
8:43 AM
↓との違いは何かだね。 class C1 { init(_ x: Int) {} } class C2: C1 { init(_ x: String) { super.init(42) } }
Avatar
omochimetaru 6/19/2020 8:43 AM
ジェネリックシグネチャの部分は関数のシグネチャ(オーバライド関係になる同一性判定)に含めてないんだと思います。 (edited)
Avatar
これって判定を緩めれば特に問題が起こらない話なのかな?
Avatar
omochimetaru 6/19/2020 8:44 AM
PかつQである型を定義することができるので
8:44 AM
その場合どっちを呼び出したいか曖昧になる問題はありそうですね
Avatar
C2 経由で C1init は呼べないのでは?
8:46 AM
C1initC2 を使うときには見えないので。
Avatar
omochimetaru 6/19/2020 8:46 AM
init2つの話だと確かにそうかも。
8:47 AM
ただそこのルールは普通のfuncとかと同じにしておいたほうがルールがシンプルになるしわかりやすいのでこれで良いと思う。 (edited)
Avatar
@swift-5.2.5 class C1 { init(_ x: Int) {} } class C2: C1 { init(_ x: String) { super.init(42) } } print(C2(42))
Avatar
exit status: 1 with stderr:<stdin>:11:10: error: cannot convert value of type 'Int' to expected argument type 'String' print(C2(42)) ^
Avatar
うーん、わざわざ required を設けてるんだから、そこはちゃんと動いてほしい気が。
8:48 AM
サブクラスでイニシャライザの引数の型を変えるなんて普通にあることで、その一部が封じされてる。他の言語だと普通にできるよね?
Avatar
omochimetaru 6/19/2020 8:49 AM
他の言語だとメタタイプオブジェクトが無いことが多いのでイニシャライザ自体のオーバライドという概念が無いですね。
Avatar
はい。なので普通にできる。
Avatar
omochimetaru 6/19/2020 8:49 AM
SwiftのObjectiveC由来っぽい部分だ。
Avatar
で、 Swift はそれを required を導入することでせっかく区別したのに、
Avatar
omochimetaru 6/19/2020 8:52 AM
requiredじゃなくてもoverrideできるから、区別と言って良いのかわからない。
8:53 AM
話の順番が違う気がするんですよね
8:53 AM
・関数同士のシグネチャを比べて、サブクラス側のそれがオーバライドできるシグネチャだったら、override  をつけることを強制する (edited)
8:54 AM
というルールが先にあって、 funcでもinitでもそれは同じように適用されているってだけじゃないですか? (edited)
8:54 AM
そういう作りになっていないと
8:54 AM
オーバーライドしたつもりでオーバーライドできていなかったバグが出てきちゃうから
8:54 AM
override 指定子は、オーバライド制御をするものじゃなくて、その承認マークをプログラマがつける物になってる。
Avatar
required じゃないときの init のオーバーライドって何のためにあるの?
Avatar
omochimetaru 6/19/2020 8:55 AM
さっきの例と説明じゃ不足ですか? (edited)
Avatar
あー、さっきのはそうか。
Avatar
omochimetaru 6/19/2020 8:55 AM
<metatype>.init で呼び出すことはできないけど、 別のinitからself.init で呼び出すことはできるので、 そこで動的ディスパッチが発生するので、関数型の互換性を保ってオーバライドされてないといけない
8:55 AM
もうこれ以上説明を分解できない。
8:57 AM
話してて逆にわかってきたけど、 required ってのは、メタタイプに対して呼び出せる事を示す(それ故にoverrideが強制される)って機能だったのか。 (edited)
8:57 AM
で、それとは別に、そもそもinitは継承できるダイナミックなものであると。
Avatar
init はサブクラスから不可視なわけではなくて、オーバーライドしないと普通に使えるからいいのか?? @swift-5.2.5 class C1 { init(_ x: Int) {} } class C2: C1 {} print(C2(42))
Avatar
main.C2
Avatar
でも、それなら↓ができないの変じゃない? @swift-5.2.5 class C1 { init(_ x: Int) {} } class C2: C1 { init(foo: String) {} } print(C2(42))
Avatar
exit status: 1 with stderr:<stdin>:9:10: error: missing argument label 'foo:' in call print(C2(42)) ^ foo: <stdin>:9:10: error: cannot convert value of type 'Int' to expected argument type 'String' print(C2(42)) ^
Avatar
omochimetaru 6/19/2020 9:01 AM
それは、 override init の自動実装なんじゃないだろうか。
Avatar
普通のメソッドと異なる挙動のものを、メソッドと同じオーバーライドルールを割り当てるのは変な気がする。
Avatar
omochimetaru 6/19/2020 9:01 AM
サブクラスにinitが1つも無いとき、自動でやる。
9:03 AM
class C1 { init() {} } class C2 { private init(_ a: Int) {} } C2() // error
9:03 AM
class C1 { init() {} } class C2 { } C2() // ok これはC1.initが見えてるんじゃなくて、C2.initが自動定義されてるんじゃないだろうか。 C++の自動コンストラクタ定義みたいなノリで。
9:04 AM
class C1 { required init(a: Int) {} init(b: Int) {} } class C2 { } C2() ↑よくViewController書いてるとなるやつ
9:06 AM
class C1 { required init(a: Int) {} init(b: Int) {} } class C2: C1 { override init(b: Int) { super.init(b: b) } // 'required' initializer 'init(a:)' must be provided by subclass of 'C1' }
9:06 AM
サブクラス側にひとつでも何かしらのinitがあると、自動実装がなくなるから、required initのoverrideしてないよって言われる。
Avatar
うーん、さっきの required convenience init からオーバーライドされた init を呼び出すパターンがあるのはいいとして、
Avatar
omochimetaru 6/19/2020 9:07 AM
class C1 { required init(a: Int) {} init(b: Int) {} init(c: Int) {} } class C2: C1 { required init(a: Int) { fatalError("init(a:) has not been implemented") } override init(b: Int) { super.init(b: b) } // init(c: Int) はなくてOKだけど、 // C2.init(c: 3) は呼び出せない } でも、requiredではないinitについては、オーバライドしないことも許されている。(ただし直接呼び出せない) (edited)
Avatar
ん?そのパターンでオーバーライドしないとどうなるんだ??
Avatar
omochimetaru 6/19/2020 9:08 AM
C2にあるinitは、(a:)と(b:)だけ。
9:10 AM
もし、C2を空っぽにした場合は、自動実装されるから、(a:)と(b:)と(c:)全部がC2にある。 (edited)
9:13 AM
initならなんでも動的ディスパッチでオーバライド可能というのが前提で、 requiredだと外から呼び出せる、requiredじゃなかったら、selfからしか呼び出せない。 というルールですね。
Avatar
@swift-5.2.5 protocol P1 {} protocol P2: P1 {} struct S1: P1 {} struct S2: P2 {} class Animal { init<X: P2>(_ x: X) { } required convenience init() { self.init(S2()) } } class Cat: Animal { let foo: Int init(foo: Int) { self.foo = foo super.init(S2()) } } func main<A: Animal>(_ animalType: A.Type) -> A { animalType.init() } let cat = main(Cat.self) print(cat.foo)
Avatar
exit status: 1 with stderr:<stdin>:21:1: error: 'required' initializer 'init()' must be provided by subclass of 'Animal' } ^ <stdin>:11:26: note: 'required' initializer is declared in superclass here required convenience init() { ^
Avatar
Catinit(_:) をオーバーライドしても何も言われないけど、オーバーライドじゃない init を作ると init()init(_:) ではない)をオーバーライドしろと言われる。おもしろい。 (edited)
Avatar
omochimetaru 6/19/2020 9:18 AM
これどういうルールなんだ・・・?
9:18 AM
サブクラスにinitがあっても、オーバライドしろって言われない場合がありますね。
Avatar
↑のケースでは init(foo:) を作ったことで init(_:) が不可視になって
9:19 AM
そうすると init() が困るから init() をオーバーライドしろと言われてる?
9:20 AM
なにせ init(_:) では foo を初期化できないしね。
Avatar
omochimetaru 6/19/2020 9:21 AM
class C1 { init(b: Int) {} required convenience init(e: Int) { self.init(e: 1) } } class C2: C1 { override init(b: Int) { super.init(b: b) } } // OK
9:21 AM
class C1 { init(b: Int) {} init(c: Int) {} required convenience init(e: Int) { self.init(e: 1) } } class C2: C1 { override init(b: Int) { super.init(b: b) } // NG: init (e) must be provided }
9:22 AM
convenienceとdesignatedで2段階の処理になっている気がする。
9:23 AM
もし、サブクラス側にdesignated initが存在しなければ、全てのdesignated initを自動オーバライドする。 もし、全てのdesignated initがオーバライドされていて、 サブクラス側にconvenience initが存在しなければ、 convenience initのオーバライドが自動実装される。
Avatar
convenience は自動オーバーライドなのかなぁ。
9:24 AM
というか、自動オーバーライドという概念がなくてもうまく動く気が。
Avatar
omochimetaru 6/19/2020 9:26 AM
class C1 { init(b: Int) {} convenience init(c: Int) { self.init(b: 1) } convenience init(d: Int) { self.init(b: 1) } } class C2: C1 { init(f: Int) {} convenience init(c: Int) { self.init(f: 1) } } C2(d: 1) // NG
Avatar
うーん、 Swift の関数って参照型なのに === で比較できないから、同じものなのか調べられなかった・・・。
Avatar
omochimetaru 6/19/2020 9:26 AM
この場合、convenienceも見えなくなる↑
Avatar
C2 に独自の init を作ったら全部見えなくなっていいんじゃない?
Avatar
omochimetaru 6/19/2020 9:27 AM
その「見えなくなる」が、見えなくなってるんじゃなくて、「見える」ように思えるのは、自動実装って事じゃないかなと思っている
Avatar
まあ、自動オーバーライドかスーパークラスのが見えるのかはセマンティクス的には見分けられないからどちらでもいい気が。
Avatar
omochimetaru 6/19/2020 9:28 AM
見えなくなるセマンティクスがよくわからない。
9:29 AM
あ〜、サブクラスのdesignated initがある場合必ずソレを呼ばないと初期化できないって事かしら
Avatar
サブクラスで init を作らない限り全部透過してる。
9:29 AM
独自 init があるケースでは独自の初期化が必要かもしれないから、透過させられない。
Avatar
omochimetaru 6/19/2020 9:30 AM
class C1 { init(b: Int) {} convenience init(c: Int) { self.init(b: 1) } convenience init(d: Int) { self.init(b: 1) } } class C2: C1 { convenience init(c: Int) { self.init(b: 1) } } C2(d: 1) // OK
9:30 AM
convenience initは、動的ディスパッチでは無いっぽい?
9:30 AM
自身のdesignated initを呼ばないといけないから、継承できたらまずいんだろうか。
Avatar
convenience では独自の初期化は行われないから、透過/自動生成のままでもいいんじゃない?
9:31 AM
うん。 designated が存在するだけでそいつを経由しないと壊れる(可能性がある)から、透過/自動生成が封じられる。
Avatar
omochimetaru 6/19/2020 9:32 AM
class C1 { init(b: Int) {} convenience init(c: Int) { print("C1.init(c:)") self.init(b: 1) } convenience init(d: Int) { self.init(c: 1) } } class C2: C1 { convenience init(c: Int) { print("C2.init(c:)") self.init(b: 1) } } C2(d: 1)
9:32 AM
C1.init(c:) が出力された。確かにオーバライドではないっぽい。
9:33 AM
class C1 { init(b: Int) {} required convenience init(c: Int) { print("C1.init(c:)") self.init(b: 1) } convenience init(d: Int) { self.init(c: 1) } } class C2: C1 { required convenience init(c: Int) { print("C2.init(c:)") self.init(b: 1) } } C2(d: 1)
9:33 AM
required convenience initだとオーバーライドされる。
9:33 AM
C2.init(c:) が出力された。
Avatar
これはこうなるのか。ということは、 convenience init をうまく使えばやりたかったこともできるのかも?
9:35 AM
狭める分を convenience にできれば。
Avatar
omochimetaru 6/19/2020 9:36 AM
サブクラスのほうが受ける型を狭めたいんでしたっけ? (edited)
Avatar
はい。
9:38 AM
ジェネリックにするからダメな気がしてきた。
9:38 AM
やりたいこととしては protocol C1Delegate { func foo() -> Int } protocol C2Delegate: C1Delegate { func bar() -> String } class C1 { init(delegate: C1Delegate) {} } class C2: C1 { init(delegate: C2Delegate) { super.init(delegate: delegate) } } みたいな感じなんだけど(これはできる) (edited)
9:39 AM
このプロトコルが existential にできない( associatedtype を持っている)からジェネリックに受けてから対処しようとしたけど、
9:40 AM
渡す時点で type erasure に包むようにすればいける?
Avatar
omochimetaru 6/19/2020 9:41 AM
うーん、convenience initにしても無理やりオーバライド判定されて間違ってるよって言われちゃってダメだな。
9:42 AM
先にまずrequiredとかconveienceとか取っ払ってシグネチャだけでオーバライド関係を解決してそう。
9:42 AM
その後でもろもろの指定子に基づいてチェック。
9:43 AM
type erasureならただの型なのでできると思うけど使う側がしんどいですね
9:45 AM
protocol P1 {} protocol P2: P1 {} class C1 { init<X: P1>(p: X) {} } class C2: C1 { convenience init<X: P2>(p2: X) { self.init(p: p2) } } 当然ラベルを変えればいけるけど・・・
Avatar
動的ディスパッチされない convenience でもダメなのかぁ。
Avatar
omochimetaru 6/19/2020 9:48 AM
convenienceつけなさいみたいな診断が出ることがあるし、その判定は後なんでしょうね。
9:48 AM
理屈上は静的なconvenienceだけはシグネチャ無視で実装できて良いはずだけど
Avatar
↑についてだけど、 module AC1 を宣言し、 module BC1extensionconvenience init<X: P1>(_ x: X) を作り、 module CC2init<X: P2>(_ x: X) を作ったらどうなるんだろう?(試せばわかる話だけど・・・) (edited)
Avatar
omochimetaru 6/22/2020 4:12 AM
この記事では、Swiftコンパイラを直接使って、コードを実行したり、モジュールを分割ビルドする方法を解説します。 この内容を理解すると、Swiftのビルドの仕組みの理解が深まるでしょう。また、コンパイラに対していろいろな実験をする上...
👀 1
4:12 AM
モジュール分割したときの型チェックだけ実験する方法を↑に多分書いた
Avatar
@objc var cat: Bool って isCat 作らないですよねえ
🤔 1
6:35 AM
@property (nonatomic, getter=isCat) BOOL cat 互換の @objc var ってどう書くんだろう
6:36 AM
Swift的には、var isCat: Bool のほうが良くて、だから setter だけ setCat: で見えるようにすればいいのかな? (edited)
6:37 AM
@objc var isCat: BoolisCatsetIsCat: を作った...
Avatar
omochimetaru 6/22/2020 6:38 AM
class ExampleClass: NSObject { @objc var enabled: Bool { @objc(isEnabled) get { // Return the appropriate value } } }
6:39 AM
getterとsetterにそれぞれobjc側の名前を指定できそう。
Avatar
storedは無理か
Avatar
omochimetaru 6/22/2020 6:39 AM
あ〜そっか。
Avatar
@objc(getter, setter) みたいには無理そう
Avatar
omochimetaru 6/22/2020 6:40 AM
The objc attribute optionally accepts a single attribute argument, which consists of an identifier.
だし、そういう記法はなさそうですね。
Avatar
なるほどー。
6:41 AM
proxy用意してあげることになるのか...
Avatar
omochimetaru 6/22/2020 6:41 AM
ドキュメントあんまり信用してないのでコンパイラほじくったらなんか裏技あるかもわからんが
6:41 AM
少なくとも僕は知らない。
Avatar
これなんかずっと疑問で Objective-CのBOOLは、isCat, setCat: になるように getter= を書くのがなんというか習慣なんだけど
6:42 AM
@objc はそんなことしてくれないんですよねえ
Avatar
omochimetaru 6/22/2020 6:42 AM
習慣というかBOOLだと @property が自動で isXxx を作りませんでしたっけ? (edited)
Avatar
しかも Swift はいつのまにか Bool のは isCat が主流に。 (edited)
Avatar
omochimetaru 6/22/2020 6:43 AM
Swiftが isCat なのはかなり初期からそうだったはず
Avatar
つくんないですね。getter=isCat って Appleのヘッダーにはほとんど書かれてる
6:43 AM
最初でたときは is ついてなかったと思ったんだけどなあ。
6:44 AM
1のころ。
Avatar
omochimetaru 6/22/2020 6:44 AM
そうか。あ〜、自動で is・・・ になるのはKotlinがJavaをimportするときかも。
Avatar
並行世界の話だったw
Avatar
omochimetaru 6/22/2020 6:44 AM
混ざった。
6:44 AM
Javaでgetterとsetterなやつをkotlinで勝手にプロパティに見せかけるんですよね
Avatar
POJOみたいなやつのか
Avatar
omochimetaru 6/22/2020 6:47 AM
Kotlinから見たJavaのクラスはなんでもその変換かかります
6:47 AM
Swiftの @objc
6:47 AM
Swift側から ObjC 向けに ObjC らしいクラスを提供する気概をあまり感じない
Avatar
Kishikawa Katsumi 6/22/2020 6:49 AM
衝突が回避できればO K、くらいの感じかもしれないですね。 (edited)
Avatar
omochimetaru 6/22/2020 6:50 AM
Swiftにマイグレーションしていく上で最低限困らないようにするって感じで
6:51 AM
ObjCと長く良く連携していく、までは見てない印象。 (edited)
Avatar
確かに...
6:53 AM
時代に逆行する昨日は提供する意義も薄い...
Avatar
omochimetaru 6/22/2020 6:54 AM
これなんかずっと疑問で
niwさんがそう感じるのは業務内容的にもわかるけど
6:54 AM
実際(昔の)MLとかForumとか見てた限りでは (edited)
6:54 AM
そのあたり掘り下げて不便なんじゃなんとかしてくれ〜って言う人は全然居ないです
6:55 AM
@objc 属性周りの SE proposal とかの前後ではちょっと話題があったけど、あんまりそこから話題も広がらなかったと思う
Avatar
んー、っていうか他の @objc は名前が習慣に合うように頑張ってるのに
6:56 AM
BOOLのproperyだけそうなってなくて、
6:56 AM
しかも途中(2だっけ)でisつけたりしてうーんって思ってた。 (edited)
Avatar
omochimetaru 6/22/2020 6:56 AM
あ〜なるほど。たしかにメソッド名のwith周りとか妙に頑張ってますもんね。
Avatar
そう。withとか。
Avatar
isXXXに関する誤解はこれかな? objcくんはBOOLなプロパティに自動でisXXXというsetterを作らないけど、KVCくんはxXXをkeyにするとインスタンス変数isXXXを検索します。
Avatar
あー、それも理由で getter=isCat が習慣になってる? (edited)
Avatar
Kishikawa Katsumi 6/22/2020 9:17 AM
isXXXは無くても動くのでむしろisXXXや_XXXの慣習があるからKVC側が気を遣ってるんじゃないですか。
Avatar
Swift 5.3から導入された@mainを使って、SwiftUIのエントリポイントが↓みたいに簡潔に書けるようになってるの面白いですね。 // SwiftUI side public protocol App { public init() ... } extension App { public static func main() -> { ... } } // App side @main struct MyApp: App { var body: some Scene { ... } } (edited)
Avatar
おーすごい
Avatar
正規のエントリポイントがprotocol extensionで実装されてるがゆえに、アプリの起動をフックしようとすると、こんな感じなる @main struct MyApp: App { static func main() -> Void { print("Hello") func takeApp<T: App>(_: T.Type) { T.main() } takeApp(Self.self) } }
Avatar
それって本質的に // app.swift struct MyApp: App { ... } // main.swift SwiftUI.main(MyApp.self) と変わらないと思ってて (edited)
11:48 AM
嬉しいのってワンファイルになった(main.swiftが不要)だけよね?
11:49 AM
フック
プロトコルデフォルト実装を呼び出すために型落として <T: P> にするテクだ。
11:50 AM
あんまり嬉しさが理解できないままproposalからアレヨアレヨとacceptしてSwiftUIで出荷されてきた。
Avatar
これmain無限ループしないの
11:50 AM
まーなんかこれに関しては
11:50 AM
@UIApplicationMain よりはマン倍マシでしょ、ということなんじゃないですかね
11:51 AM
@UIApplicationMain を今更駆逐は出来ないし
Avatar
まーそうですねー
Avatar
あれ、無限ループしそうに見える。requirementsあるよね?
Avatar
いや、Appプロトコルの方にrequirements無いんですよ
Avatar
ないのか。
Avatar
なのでデフォルト実装へのディスパッチは常に静的になる
Avatar
@main に基づいて静的書き換えされているだけなのね。
11:53 AM
「requirementsが無いからデフォルトが呼べる」って世界観はモヤっとするなw
Avatar
実装を知ってるとそうだよね、ってなるけど知らないと意味不明ですよね
Avatar
まあまあマニアックだね。
11:55 AM
@UIApplicationMain@main になるなら確かに統一されてマシになるね・・・
Avatar
このオーバーライド邪悪だなと思ったらSR-106の挙動を利用してるのかw
Avatar
staticだけどまあそういうことだね。
11:56 AM
SwiftUIをマスターするにはSR-106の理解が必要!
11:57 AM
その辺も main.swift だったら 前後をフックするのとか自明にできるんだけどなあ。
Avatar
106じゃなくて103でした、すぐ忘れる
11:59 AM
あーでもこれはスーパークラスの宣言の有無だからまた別か
Avatar
それよりは邪悪度低いですね
Avatar
この挙動は知っているのでもしかしたら報告してたかもしれねえ
Avatar
こうすると素朴にフックできるけど、もはや@main使う意味が無い @main struct Entry { static func main() -> Void { print("Hello") MyApp.main() } } struct MyApp: App { var body: some Scene {...} }
Avatar
むしろ素朴にして @main 使わないほうが良いのでは。。。
Avatar
それはそう…
Avatar
main.swiftでよかったじゃんってなるやつ。
12:04 PM
まあ1ファイルなのがちょっとだけ嬉しいか。
Avatar
https://forums.swift.org/t/question-re-5-3-function-builder-enhancement-let-is-allowed/38055/12 Dictionary[_:default:] がデフォルト値を元のDictionaryに挿入してくれないのを解決するために Dictionary[_:orInsert:] っていうのを付加してるんだけど、その実装が面白い。 extension Dictionary { public subscript(key: Key, orInsert value: @autoclosure () -> Value) -> Value { mutating get { // We have to "mutate" the result of subscript[_:default:] in order // to ensure an entry gets added, so we pass it inout to a function. return { $0 }(&self[key, default: value()]) } } } { $0 }(&mutableValue) で値を返すと同時に $0inout と解釈されて mutableValue の setter がトリガーされる。 (edited)
Avatar
おもしろいですね。
11:36 PM
この使い方はおもしろいけど、 mutating get はちょっと混乱を招きそうな気も・・・。
Avatar
dictionary[key, default: 0] += 1 とかも (+=)(&dictionary[key, default: 0], 1) のように考えれば同じような感じになって、 { $0 }(&self[key, default: value()]) の発想になるのかな。
Avatar
おー、なるほど。確かにassignment operator っぽさありますね。 prefix operator % prefix func % <T>(_ val: inout T) -> T { val } var dict = ["foo": 1] _ = dict["bar", default: 2] print(dict) // -> ["foo": 1] _ = %dict["bar", default: 3] print(dict) // -> ["bar": 3, "foo": 1]
Avatar
もし↑の % が採用されたら、 $ に加えて初見殺しの謎の記号が Swift にw
12:53 AM
callAsFunction の無名 function 案が検索性の問題で見送られたのに、 Property Wrapper で $ が採用されてるのダブスタ感がある気が。
12:54 AM
declaration site と call site の違いはあるとはいえ。
Avatar
norio_nomura 7/2/2020 1:12 AM
value()が2回実行されそうな気もしたけど、inoutになった時点で_modify {…}が呼び出されるから、そうはならないのね。 @swift-5.3.3 extension Dictionary { public subscript(key: Key, orInsert value: @autoclosure () -> Value) -> Value { mutating get { // We have to "mutate" the result of subscript[_:default:] in order // to ensure an entry gets added, so we pass it inout to a function. return { $0 }(&self[key, default: value()]) } } } var d: [String: Int] = [:] print(d["a", orInsert: {() -> Int in print("closure"); return 1}()]) print(d)
Avatar
swift53 BOT 7/2/2020 1:12 AM
closure 1 ["a": 1]
Avatar
Dictionarysubscript[_:default:]set って、 +=inout )とかチェーンの途中で使わず単独で使ったときって特に意味ないですよね? dictionary[key, default: 0] = 1 みたいなの。
1:35 AM
@swift-5.2.5 struct Foo { var value: Int = 0 } let key = "key" func foo() -> Foo { print("`foo()` is called.") return Foo() } var dictionary: [String: Foo] = [:] dictionary[key, default: foo()].value = 42 print(dictionary)
Avatar
swift52 BOT 7/2/2020 1:35 AM
`foo()` is called. ["key": main.Foo(value: 42)]
Avatar
inout じゃなくても 1 回しか呼ばれない。
1:42 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
1:47 AM
set が何もしてないんじゃなくて、 _modify のおかげで一度しか呼ばれない?
1:49 AM
キーを2回引かなくてよくなってるのか。
Avatar
norio_nomura 7/2/2020 1:58 AM
_modifyではなくsetで書かれていたとしても、setの場合はdefaultValueが不要だから、一度しか呼ばれないですね。 @swift-5.3.3 extension Dictionary { public subscript(key: Key, default2 defaultValue: @autoclosure () -> Value) -> Value { get { print("get") return self[key] ?? defaultValue() } set { print("set") self[key] = newValue } } public subscript(key: Key, orInsert value: @autoclosure () -> Value) -> Value { mutating get { { $0 }(&self[key, default2: value()]) } } } var d: [String: Int] = [:] print(d["a", orInsert: {() -> Int in print("closure"); return 1}()]) print(d)
Avatar
swift53 BOT 7/2/2020 1:58 AM
get closure set 1 ["a": 1]
Avatar
その場合 getset で 2 回 self[key] でハッシュテーブルを引くことになりますよね?
3:06 AM
あ、 value が一度しか呼ばれないのはいいんですが、元々 @norio_nomura さんが書いた _modify を使わないような実装になってるのかと思ってましたが、 _modify を使うことでそれだけじゃなくてハッシュテーブルを一度しか引かなくて済んでるんだなと。
Avatar
norio_nomura 7/2/2020 3:09 AM
ですね。
Avatar
Objective-Cのprotocolにconformすると@objcになるんだっけ...?
Avatar
ObjCで宣言されたprotocolの事なら、NSObjectProtocolがbaseになっていて、これに宣言された関数は暗黙的に@objcになっていたと思います。また、実装先はNSObjectであることを要求されます。
Avatar
なるほど、特に何もしなくてもそうなってたからそうなのかなって感じてたけど。 (edited)
1:46 AM
NSObjectProtocolが暗黙的にいろいろしてくるのか...
Avatar
2とか3の頃はかなり色々やってたんですが、4か5くらいから@objcを暗黙的につけるのを辞めるぞ〜みたいなのがあった記憶が朧気に
1:50 AM
今どうなってんだろ
1:52 AM
ちょっとPlayground触った感じ、Swiftで宣言したNSObjectProtocolの場合は、@objcを明示してねって怒られますね
😳 1
Avatar
import Foundation protocol Foo: NSObjectProtocol { func a() } class Bar: NSObject, Foo { func a() { } } // Foo2はObj-C headerに宣言 class Bar2: NSObject, Foo2 { func a() { } } // true print(class_getInstanceMethod(Bar.self, Selector("a")) == nil) // false print(class_getInstanceMethod(Bar2.self, Selector("a")) == nil) (edited)
2:00 AM
Protocolの出身地で暗黙的に@objcになるかどうかの挙動が変わりますねw
Avatar
@swift-5.2.5 import Foundation protocol P: NSObjectProtocol { optional func f() }
Avatar
swift52 BOT 7/3/2020 5:25 AM
exit status: 1 with stderr:<stdin>:4:3: error: 'optional' can only be applied to members of an @objc protocol optional func f() ^~~~~~~~~
Avatar
暗黙的に@objcにならない
Avatar
どこ由来なのかによる...?
Avatar
うーん、なかなか恐ろしいな。
12:15 PM
interface作ってる側がSwiftに書き換えちゃったら動かなくなる、とかあるのか。
Avatar
@swift-5.2.5 protocol Container { associatedtype Item var item: Item { get } } struct MyContainer<T>: Container { var item: T } extension Container { func transform<T>(_ f: (Self.Item) -> T) -> some Container { MyContainer(item: f(self.item)) } } let c1 = MyContainer(item: 1) let c2 = c1.transform { item in item + 1 } let item: Int = c2.item print(item)
Avatar
swift52 BOT 7/4/2020 8:59 PM
exit status: 1 with stderr:<stdin>:21:20: error: cannot convert value of type '(some Container).Item' to specified type 'Int' let item: Int = c2.item ~~~^~~~ as! Int
Avatar
ぇー...
9:00 PM
Opaque Type...
Avatar
リバースジェネリクスが欲しくなるパターンっぽい
Avatar
リバースジェネリクスか、(今はまだできない) some Container<.Item == Int> some Container<.Item == T> (edited)
Avatar
ちなみに :Int がなければ大丈夫...
Avatar
.Item == T ですかね
Avatar
ああ、そうですね。
12:30 AM
:Int がなくても Int になってるわけではないから、
12:30 AM
@swift-5.2.5 protocol Container { associatedtype Item var item: Item { get } } struct MyContainer<T>: Container { var item: T } extension Container { func transform<T>(_ f: (Self.Item) -> T) -> some Container { MyContainer(item: f(self.item)) } } let c1 = MyContainer(item: 1) let c2 = c1.transform { item in item + 1 } let item = c2.item print(item + 1)
Avatar
exit status: 1 with stderr:<stdin>:22:7: error: cannot convert value of type '(some Container).Item' to expected argument type 'Int' print(item + 1) ^ as! Int
Avatar
print は何でも渡せるから動いているだけのよう。
Avatar
なんですよねえ
12:32 AM
some の使い所...
12:32 AM
AnyContainer<T> みたいなのがまだ必要
Avatar
some Foo<.Bar == Baz> が書けるようになるまでは、
12:33 AM
some View みたいな、かなり使いどころが限られると思います。
Avatar
some View は associated type ないんだっけ。
Avatar
Body が assoc type ですが、型パラ的性質のものじゃないので成り立ってます。
Avatar
なるほど
Avatar
あと、 anysome は性質が違うので、 some View はできるけど AnyView もあります。
12:36 AM
Generalized Existential が導入され(て any 修飾子も導入され)たら any View と書けるようになるかと。
12:36 AM
@Douglas_Gregor wrote the Generics Manifesto almost three years ago, which provided the roadmap for the core of Swift's protocols and generics features. Since then, we've implemented almost all of the basic model that it envisioned. Although there are further features we could...
Avatar
とうぶんかかりそう...
Avatar
some Foo<.Bar == Baz> についても、↓のセクション( Expressing constraints directly on arguments and returns )で言及されてます。僕はこの記法で anysome が統一されるのが良いと思います。 https://forums.swift.org/t/improving-the-ui-of-generics/22814#heading--directly-expressing-constraints
@Douglas_Gregor wrote the Generics Manifesto almost three years ago, which provided the roadmap for the core of Swift's protocols and generics features. Since then, we've implemented almost all of the basic model that it envisioned. Although there are further features we could...
12:39 AM
今のところ動きがなさそうなので、当分かかるのは間違いないと思います。おそらく Swift 6.0 では来ないでしょうね・・・。
12:40 AM
any だけなら Parser の問題なので、早めに導入してほしいですが・・・。
Avatar
SwiftUI ドリブンで今の some だけ入った感がある (edited)
Avatar
そうだと思います。
Avatar
気のせいかもしれないけど、オーバーロードが曖昧になってしまうときに、一方を優先させる黒魔術とか _ 付き attribute とかありませんでしたっけ?
Avatar
omochimetaru 7/7/2020 5:41 AM
@_disfavoredOverload
Avatar
お、ありがとう。
5:42 AM
個人的に実用はすすめないけど・・・↑で紹介してます。
5:42 AM
P28, 29.
👍 1
Avatar
https://discordapp.com/channels/291054398077927425/375206337937801216/698578768696049664 を応用して、イニシャライズできない型のデフォルト引数を与えるとかもありかな? (edited)
5:43 AM
それはデフォルトにできないか?
Avatar
omochimetaru 7/7/2020 5:43 AM
デフォルト引数の有無は同じスコアのときのさらなるオーダー付けじゃないかしら
5:44 AM
あー、visibilityの問題でデフォルトにできないですね
5:44 AM
デフォルト引数の評価はcaller contextです
Avatar
さっきの #combine で話してた FuturegetFailureNever のときだけ Result<Output, Never> じゃなくて Output で受け取るようにできた。 @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Future { @_disfavoredOverload public func get(_ body: @escaping (Result<Output, Failure>) -> Void) { let keep: Keep<AnyCancellable> = .init() keep.value = sink(receiveCompletion: { completion in switch completion { case .finished: break case .failure(let error): body(.failure(error)) } keep.value = nil }, receiveValue: { output in body(.success(output)) }) } } @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) extension Future where Failure == Never { public func get(_ body: @escaping (Output) -> Void) { let keep: Keep<AnyCancellable> = .init() keep.value = sink { output in body(output) keep.value = nil } } } private class Keep<Value> { var value: Value? }
5:48 AM
@_disfavoredOverload がないと ambiguous になってしまう。 (edited)
Avatar
omochimetaru 7/7/2020 5:55 AM
これambiguousかあ
5:56 AM
Failureに関して厳しさが上がってるから優先度差付いて欲しい感じがする
5:57 AM
あれ?てか、Neverではない方がdisfacoredなのか。
Avatar
いや、 ambiguous だったから同じ順位かな?
6:11 AM
引数の型違いのオーバーロードだから ambiguous でも正しい気がするんよね。
Avatar
omochimetaru 7/7/2020 6:11 AM
はい。スコアは同じ上で、generic signatureの差でNeverの方になってほしいと思った。
Avatar
Output|FailureOutput になったなら後者を選んでほしいけど。
Avatar
omochimetaru 7/7/2020 6:12 AM
引数が違って比較不能なんかな、そこのルールまだ未調査で。
Avatar
generic signatureの差でNeverの方になってほしいと思った。
これって、たとえば extension Future { func foo(_ f: (Int) -> Void) { ... } } extension Future where Failure == Never { func foo(_ f: (String) -> Void) { ... } } だとしても後者が選ばれてほしいってこと?
6:14 AM
全く無関係なオーバーロード。
Avatar
omochimetaru 7/7/2020 6:15 AM
基本は前者が選ばれてほしくて、Failure == Neverになる情報があるときは後者になってほしい。
6:15 AM
あ違うか、前者になるような時は曖昧なのか?
6:16 AM
少なくとも、Failure == Never になるときは、厳しい方なので確定して欲しい、か。
Avatar
future.foo { x in ... } みたいに書いたときにどっちになってほしいか(もしくは ambiguous でエラーか)だね。
6:17 AM
↑の場合って、 Failure == Never のときに foo のオーバーロードが追加されてるだけで、個人的には優先度が並列なのは納得なんだよなぁ。
6:18 AM
IntString じゃなくて Result<Output, Never>Output だと、型の上では変わらないんだけど、意味的には狭まってるから後者が選ばれてほしい気持ちになるけど・・・。
Avatar
omochimetaru 7/7/2020 6:20 AM
Result<Output, Never>Output って意味的には狭まってるけど、型空間的には広がってますね
6:21 AM
Output は 任意の Result<A, B> を包含するから。
Avatar
あー、それ辛そう😂
6:23 AM
@swift-5.2.5 class Animal {} class Cat: Animal {} struct Foo<Value> { var value: Value } extension Foo { func f() -> Animal { Animal() } } extension Foo where Value == Int { func f() -> Cat { Cat() } } print(Foo<Int>(value: 42).f())
Avatar
swift52 BOT 7/7/2020 6:23 AM
main.Cat
Avatar
これだと優先されても納得。
Avatar
omochimetaru 7/7/2020 6:24 AM
返り値も狭まってるし文句ないですね
Avatar
@swift-5.2.5 class Cat {} class Dog {} struct Foo<Value> { var value: Value } extension Foo { func f() -> Dog { Dog() } } extension Foo where Value == Int { func f() -> Cat { Cat() } } print(Foo<Int>(value: 42).f())
Avatar
swift52 BOT 7/7/2020 6:25 AM
main.Cat
Avatar
↑が ambiguous にならないの変じゃない?
6:26 AM
いや、 OutputResult<Output, Never> を含んでいるから ambiguous になってるだけ?
Avatar
omochimetaru 7/7/2020 6:27 AM
これは返り値に関しては狭まってないけど、原則はそうなるという理解
6:28 AM
元々のやつも同じようになると期待した。
6:28 AM
extension where の影響でより厳しいgeneric signatureを持つほうが勝つはず・・・
Avatar
@swift-5.2.5 struct Foo<Failure: Error> { var value: Failure? } extension Foo { func f() -> Result<Int, Failure> { .success(1) } } extension Foo where Failure == Never { func f() -> Int { 2 } } print(Foo<Never>().f())
Avatar
swift52 BOT 7/7/2020 6:29 AM
2
Avatar
えー、これでもいけるなら get もいけてほしいな。
6:34 AM
@swift-5.2.5 final class Future<Output, Failure: Error> { var result: Result<Output, Failure>? } extension Future { func get() -> Result<Output, Failure>? { result } } extension Future where Failure == Never { func get() -> Output? { try! result?.get() } } let future = Future<Int, Never>() future.result = .success(42) print(future.get()!)
Avatar
swift52 BOT 7/7/2020 6:34 AM
42
Avatar
@swift-5.2.5 final class Future<Output, Failure: Error> { var result: Result<Output, Failure>? } extension Future { func get(_ body: @escaping (Result<Output, Failure>) -> Void) { guard let result = self.result else { return } body(result) } } extension Future where Failure == Never { func get(_ body: @escaping (Output) -> Void) { guard let result = self.result else { return } body(try! result.get()) } } let future = Future<Int, Never>() future.result = .success(42) future.get { value in print(value) }
Avatar
swift52 BOT 7/7/2020 6:36 AM
exit status: 1 with stderr:<stdin>:21:1: error: ambiguous use of 'get' future.get { value in ^ <stdin>:6:10: note: found this candidate func get(_ body: @escaping (Result<Output, Failure>) -> Void) { ^ <stdin>:13:10: note: found this candidate func get(_ body: @escaping (Output) -> Void) { ^
Avatar
これ二つ同じことだと思うんだけど、どうなってるんだろう?
6:37 AM
contravariant の contravariant を考えるところとかでうまくスコア計算できてないのかな?
Avatar
返り値と引数でスコアリングの形態が違うのかな
Avatar
引数の引数だから反転して戻り値と同じ扱いになってほしいところですが・・・。そのあたりがうまく考慮されてなさそう?
Avatar
omochimetaru 7/9/2020 4:01 AM
Numerical APIs for Swift. Contribute to apple/swift-numerics development by creating an account on GitHub.
4:01 AM
For this reason, modules that would have this ambiguity are suffixed with Module within Swift Numerics: import ComplexModule // I know I only ever want Complex<Double>, so I shouldn't need the generic parameter. typealias Complex = ComplexModule.Complex<Double> // But I can still refer to the generic type by qualifying the name if I need it occasionally: let a = ComplexModule.Complex<Float>
4:02 AM
パッケージ名とそのパッケージが提供する型の名前が衝突してると面倒な事になる問題に対して
4:02 AM
swift-numericsの対応方針はパッケージ名に Module suffix をつける派らしい。
Avatar
ほう。。。
Avatar
omochimetaru 7/9/2020 4:02 AM
↑の下の方の Notes のところ。
Avatar
Swift 、 suffix で解決するの好きだな。 IteratorProtocol とか。
Avatar
omochimetaru 7/9/2020 4:36 AM
KeyedDecodingContainerProtocol もありますね
4:36 AM
まあsuffixで解決されてるほうが
4:36 AM
初見の人にとっては簡単ですよね
4:37 AM
種類による解決規則を気にしなくて良いので。
Avatar
$nantoka... _nantoka...
Avatar
omochimetaru 7/9/2020 4:50 AM
PropertyWrapperのそれはだいぶ厳しいよなあ・・・
Avatar
初見殺しには間違いない
Avatar
omochimetaru 7/9/2020 4:51 AM
覚えればSwiftUIが書きやすいのはそうだけども
Avatar
たぶんSwiftUIつかってる多くの人がよくわからずにそういうもんだと使ってる気がする
Avatar
omochimetaru 7/9/2020 4:51 AM
structでView書いてState<Int> とかやるの
4:51 AM
本当にわかりやすくなってるのかずっと疑問
4:53 AM
self.age, self.$age, self._age じゃなくて self.age.value, self.age.asBinding(), self.age の方が何が起こってるかは明確だし。 最終的なコードがスッキリするのはわかるんだけども。
4:54 AM
処理系の方に値ツリーのスナップショットが残ってて差分チェックするあたりが、 全然値型的なふるまいじゃないのに雰囲気はただのstructだから混乱する
Avatar
PropertyWrapperって歴史的にSwiftUIありきで策定実装されたんですかね
Avatar
omochimetaru 7/9/2020 4:55 AM
かつそのインスタンス的なものが実ビューのイベントハンドラからイベントを受け取るところとかがすごく参照型的。 (edited)
4:55 AM
そうですよ
4:55 AM
WWDC 2019の半年前ぐらいに
4:55 AM
よくわからないプロポーザルがバコバコ通って
4:56 AM
コアチームのモチベーションがすごかったから謎だったんだけど
Avatar
ばこばこ
Avatar
omochimetaru 7/9/2020 4:56 AM
もっと基本的で一生遅延してるプロポーザルとかもあるので。
4:56 AM
PropertyWrapperとDynamic Member KeyPathLookup (edited)
Avatar
Kishikawa Katsumi 7/9/2020 4:56 AM
PropertyWrapperの提案はPropertyDelegateからだから最初はSwiftUI関係なかったと思う。
Avatar
omochimetaru 7/9/2020 4:56 AM
あ〜そうですね
Avatar
Kishikawa Katsumi 7/9/2020 4:57 AM
ただいろいろ渋ってた割に急に通ったのは完全にSwiftUIのためっぽい。
Avatar
omochimetaru 7/9/2020 4:57 AM
Property Delegateは大昔からあって超初期にまだはやいっつって停止してた。
Avatar
Kishikawa Katsumi 7/9/2020 4:57 AM
Proposalはかなり魅力的だったけどなかなか入らずで結局入るんかいって印象だった。
Avatar
omochimetaru 7/9/2020 4:58 AM
そう、放置系をそろそろやってくのか?と思ったら
4:58 AM
それだけだったから
4:58 AM
なんだったんだ・・・?って思った。
4:59 AM
まあSwiftUIは結局
4:59 AM
最大の言語拡張のFunction Builderが
4:59 AM
WWDC期間中にproposal draftが出るっていう
5:00 AM
だから結局、Xcode固有のSwiftオレオレ拡張って事になってるのもなんだかなあ。
5:01 AM
Xcode12の実装でFunction Builderの構文サポートと型推論はかなり良くなったはずだから、 まあ、そろそろproposalが出そう。
5:02 AM
たぶんSwiftUIつかってる多くの人がよくわからずにそういうもんだと使ってる気がする
それで良いような気もするしダメな気もする ずっとモヤモヤしている。
Avatar
なんかSwiftUIのことdiscloseできないから$ _ がそのままになったとかだったら
5:02 AM
悲惨だなあと思った。
Avatar
omochimetaru 7/9/2020 5:03 AM
そうなんですよね〜 SwiftUIの事を秘密にしたままで
5:03 AM
抽象的な話するから
5:04 AM
本当はSwiftUIを前提に話した方が建設的だと思うんだよな。
5:04 AM
まあうまくやってたような気もするけど。 (edited)
Avatar
Swift の例えばフレームワークとかでドキュメント生成はjazzyがデファクトなんですかね
12:47 AM
Soulful docs for Swift & Objective-C. Contribute to realm/jazzy development by creating an account on GitHub.
12:48 AM
Generates documentation for Swift projects. Contribute to SwiftDocOrg/swift-doc development by creating an account on GitHub.
Avatar
Kishikawa Katsumi 7/11/2020 2:25 AM
DefactoはJazzy、Swift Docはとても最近リリースされて(先月?)これから期待。後発だからJazzyよりパフォーマンスが軽いとか優れてる面はちょいちょいあるみたいです。
Avatar
見た感じ swift doc がモダンで
4:09 AM
jazzyは重そうな感じというか実際依存gemの量がヤバかった
4:09 AM
ただ、デフォルトの https://swiftdoc.org/ のこの見た目はちょっと 🤔 (edited)
Auto-generated documentation for Swift. Command-click no more.
Avatar
Kishikawa Katsumi 7/11/2020 4:29 AM
その依存はプロダクトに入ってこないからてんこ盛りでもいいんじゃないかな。
Avatar
もちろんそうなんですけどね
Avatar
bundleとか使ってgemがあちこちに散らばるのがいやで、jazzyのdockerイメージ作りました。 https://hub.docker.com/r/norionomura/jazzy
12:46 PM
Linux版でビルドできるものにしか使えないけど。
Avatar
Kishikawa Katsumi 7/12/2020 4:29 PM
@norio_nomura このDockerfile、途中でbundlerインストールしなくていいんじゃないですか? (edited)
4:30 PM
使ってないように見えます
Avatar
norio_nomura 7/12/2020 9:30 PM
Linux版のsourcekitten実行環境でもあるので、jazzyのgemだけbundlerでバージョンを合わせてLinuxで実行したいという要望に応える為に入ってます。 (edited)
Avatar
Kishikawa Katsumi 7/12/2020 9:44 PM
あ、なるほど。DockerImageに入って使う感じなんですか。
Avatar
そうですね、CIとかで「このstepだけdocker」とか出来ない環境向けですね。
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
ごしつもん: Result<S, F> を返す function の XCTestCase テストどうやってかいてますか?
1:44 AM
えらく冗長になりがち
Avatar
func XCTResultSuccess<T: Equatable, E>(Result<T, E>, T) func XCTResultFailure<T, E>(Result<T,E>, (E)->Bool) これ作っておけば成功はワンライン、失敗はcast一回で済みそう (edited)
1:53 AM
SuccessもBool返すクロージャーでもいいかも
Avatar
それっぽいのやったんですけど、TかEが推論できないですうあーんってswiftに言われて、まあそりゃそうかとなった
Avatar
もしかしてResult.success(1)とかで与えちゃってます?
2:24 AM
関数の返値を評価したいなら、T,Eは定まってるはずなので
Avatar
どうやってたんだったかな...
Avatar
Result<Int,Error>.success(1)とかが相当してるはず
Avatar
結局 Result.failure: Failure? Result.succss: Succes? を追加して XCTAssertEqual() で比較してる (edited)
Avatar
確かにそれは楽っぽい
Avatar
なんで👆のやつで型推論聞かなかったんだったかな... (edited)
Avatar
@swift-5.2.5 import XCTest extension String: Error {} func XCTAssertResultSuccess<T, E>(_ actual: Result<T, E>, _ expect: (T) -> Bool, file: StaticString = #file, line: UInt = #line) { switch actual { case .success(let value): XCTAssertTrue(expect(value), file: file, line: line) case .failure(let error): XCTFail("Unexpected failure: \(error)", file: file, line: line) } } func XCTAssertResultFailure<T, E>(_ actual: Result<T, E>, _ expect: (E) -> Bool, file: StaticString = #file, line: UInt = #line) { switch actual { case .success(let value): XCTFail("Unexpected success: \(value)") case .failure(let error): XCTAssertTrue(expect(error), file: file, line: line) } } XCTAssertResultSuccess(Result<Int, Error>.success(1), { $0 == 1 }) XCTAssertResultFailure(Result<Int, Error>.failure("error"), { $0 is String })
Avatar
no output
Avatar
動くはず
Avatar
enum MyError: Error { case notEven } func f(_ a: Int) -> Result<Int, Error> { a % 2 == 0 ? .success(a) : .failure(MyError.notEven) } func assert<T: Equatable, E>(_ r: Result<T, E>, success: T) { switch r { case .success(let value): XCTAssertEqual(value, success) default: XCTFail() } } func assert<T, E: Error & Equatable>(_ r: Result<T, Error>, failure: E) { switch r { case .failure(let value): XCTAssertEqual(value as? E, failure) default: XCTFail() } } func test() { assert(f(2), success: 2) assert(f(1), failure: MyError.notEven) }
2:31 AM
できた
2:31 AM
なんでできなかったんだ...
2:32 AM
as? が消える分、failure: Failure? を使うより綺麗だなあ (edited)
Avatar
関数の返値が、T or Eを逆伝搬させるような作りになってたか、或いは
2:32 AM
Result.success(1)と即値を与えたがErrorの指定をしていなかった、かな
Avatar
そうかも
Avatar
try result.get() はだめですか? throwsfunc のテストと同じと考えれば。
Avatar
XCTAssertThrows(try result.get()) { error in ... } (edited)
2:36 AM
ですかね。
2:36 AM
ダメじゃないです。でも冗長かなあと。
Avatar
do { ... XCTAssertEqual(try result.get(), ...) ... } catch { XCTFail("\(error)") } とか。 (edited)
Avatar
拡張しないで書くのは何パターンかあるんだけどなんかそのパターンのコピペの嵐に...
2:38 AM
unit test はコピペが多い世界なのでなるべく避けたいなあと。
Avatar
Resultthrows の特殊ケースだと考えると数の少ない Resultthrows と同じでも良いかなぁと。 niw さんは throws 使わず Result 派でしたっけ? (edited)
Avatar
いや状況次第
2:42 AM
throws できないパターンもあるので。
2:42 AM
(てかthrows派/Result派とかあるの...) (edited)
Avatar
typed throws がないから基本 Result にするという意見も聞いたことがあります。
Avatar
なるほど。
Avatar
非同期処理は現状で Result 使わざるを得ないですが、 async/await が導入されたら throws async になるでしょうし、そうすると結局↑のようにテストするだろうなと考えると get 方式でもいいのかなぁと。
Avatar
throwはわりと躊躇なくつかうかな。asyncのときは Result.
Avatar
でもよく考えると async/await 導入されたら非同期テストどうなるんでしょうね? expectationwait とかも書きづらいし。
Avatar
expectationないとrunloopとか回らないから
2:57 AM
非同期のunit testしんどそうだなあ。
Avatar
コールバック化してテストとかだと嫌ですね・・・。
2:58 AM
それなら結局テスト時は Result か。
Avatar
テストする関数自体がasyncで書ければ何も問題なくなるはず
Avatar
それに対応してくれたらとても書きやすくなってうれしいです。
Avatar
func testFoo() async { // await 書き放題 🥳 } こうなる
Avatar
await書き放題w
Avatar
expectation 要らずで最高ですね。
3:00 AM
timeout が問題か。
3:01 AM
XCTestCase のプロパティで設定とかかなぁ。ちょっと気持ち悪いけど。
3:02 AM
func testFoo() async { timeout = 3.0 XCTAssertEqual(await foo(), 42) } (edited)
3:06 AM
throws async なら↓みたいな感じ? func testFoo() async { timeout = 3.0 do { XCTAssertEqual(await try foo(...), ...) XCTAssertEqual(await try foo(...), ...) XCTAssertEqual(await try foo(...), ...) } catch { XCTFail(...) } do { // error cases _ = await try foo(...) XCTFail(...) } catch error as FooError { XCTAssertEqual(error.bar, ...) } catch { XCTFail(...) } )
Avatar
swift-doc の挙動をしらべてて、
5:47 AM
Swiftではファイルをデフォルトのパーミッションで作る、ということができないような気がしている
5:47 AM
open(2)を指定したmode_tで呼ぶ術がない
5:47 AM
By quickly searching, this is the only API in Swift that can create file with open(2) (via _CFOpenFileWithMode(),) however there are no way to control this permission value. Therefore, in Swift we can’t create file with regular permission using umask. Surprise! 😟
5:47 AM
これほんとかなあ...?
Avatar
バグっぽい
6:24 AM
Remove makeTemporaryFile(inDirectory:) in favour of using _NSCreateTemporaryFile(path). FileHandle: Add internal _write(buf:length) method to write out memory buffers. FileHandle: Add a throwin...
Avatar
omochimetaru 7/30/2020 2:43 AM
Add async to the type system. async can be written as part of a function type or function declaration, following the parameter list, e.g., func doSomeWork() async { ... } async functions are distin...
2:43 AM
asyncがマージされた
2:44 AM
async関数宣言が型システムで扱えるようになっただけっぽいけど、いよいよ進むのかしら
Avatar
おおおお!
Avatar
おー
Avatar
ちゃんと async 付いてる! // CHECK: "$s5async1fyyYF" public func f() async { } // CHECK: "$s5async1gyyYKF" public func g() async throws { } https://github.com/DougGregor/swift/blob/b1802fa2eb9a03f3232a178ecbbc86ee2dfdeae3/test/IRGen/async.swift
The Swift Programming Language. Contribute to DougGregor/swift development by creating an account on GitHub.
Avatar
なにもしないasyncだ
Avatar
async だとデフォルト throws 案もあったけど、分離する案に落ち着いたのか。
2:50 AM
ってか、 Proposal 通ってなくない???
Avatar
omochimetaru 7/30/2020 2:50 AM
今はだいたいそうですよ
Avatar
通るどころか正式に出てもないよね・・・。
Avatar
omochimetaru 7/30/2020 2:50 AM
実装できてから審査行き
Avatar
Apple 「SwiftUIに必要だから足した」 (edited)
Avatar
実装してから審査はわかるけど、マージしてから審査なの?
2:51 AM
もう結論が出てるのか・・・。
Avatar
asyncはswiftUIみはあんまりないけど
Avatar
Apple「AppStoreの審査と同じ」
Avatar
omochimetaru 7/30/2020 2:51 AM
うーん例えば
Avatar
AppStoreの審査は草
Avatar
omochimetaru 7/30/2020 2:51 AM
全部の機能がマージされるタイミングでコンパイラスイッチがついて
Avatar
_modify みたいに _ も付いてないけど、いきなり async でマージなのか。
Avatar
omochimetaru 7/30/2020 2:52 AM
masterで -enable-async をつけたら使える状態で審査開始 とかは
2:52 AM
よくある
Avatar
これから出てくる Proposal が楽しみだね。
Avatar
omochimetaru 7/30/2020 2:53 AM
下敷きとなるproposal draftとかが明示されてないのは気になるけど
2:53 AM
もはやSwiftUIのFunction Builderとか未だに何も正式に通ってないし
Avatar
まあ、一応昔の Lattner のがあるからね。 < Proposal ドラフト
Avatar
omochimetaru 7/30/2020 2:54 AM
Xcode版でとりあえずリリースしたから試してみてくれ、OSS Swiftの正式採用はその後で、 もありえなくはない・・・
Avatar
そういうやつは一応 _ は付いてるのでは?
2:54 AM
今の段階で無理して async ぶちこむ必要って Apple 的にあまりなさそうだけど・・・。
Avatar
omochimetaru 7/30/2020 2:57 AM
たしかにFunctionBuilderは @_functionBuilder か。
2:57 AM
awaitは _await でやるのかな
Avatar
2日でマージって裏で結構進んでたんですね。 Futureベースのswift-nioがasyncになるだろうしまた影響大きそう……
Avatar
でもマージされたの async になってない? < アンスコ (edited)
Avatar
omochimetaru 7/30/2020 2:58 AM
async はそうですね。
Avatar
ああ、 await か。
Avatar
omochimetaru 7/30/2020 2:58 AM
await のほうはアンスコするのかなあと思っただけ
Avatar
await にはアンスコ付けるけど async には付けないその心は?
Avatar
omochimetaru 7/30/2020 2:59 AM
うーんたしか modify も最初普通に実装してすぐにアンスコつけるPRが通ったような気がする 超初期に
Avatar
たしかに後からアンスコ付いてたかも。
3:00 AM
modify も別に急ぎの理由はなかったことを考えると、 Foundation の非同期 API の対応とかもあるし、とりあえず入れて気長にやっていくのかな。 Swift 5.3 じゃなくて Swift 6 だろうし。
3:01 AM
Swift 6 、 Ownership に async/await に、色々とすごいな。 (edited)
Avatar
omochimetaru 7/30/2020 3:03 AM
手順としてはownership完成してからじゃないとasyncawait作れないよねって話が過去にあったはずで
3:03 AM
そのへんは謎
Avatar
一応 @differentiable の例もあるので、Appleだけが未審査の機能をマージしているというわけでは無い、ということは言っておきたい。
👍 1
Avatar
omochimetaru 7/30/2020 3:06 AM
differentiable確かに
Avatar
-enable-experimental-cxx-interop
Avatar
omochimetaru 7/30/2020 3:13 AM
スイッチで封印またはアンスコ付きのどっちかはやってる気がする
Avatar
omochimetaru 8/4/2020 1:51 AM
More precisely, the introduction of SE-0142 and SE-0157 has made canonical type computation into an undecidable problem. I'll begin with the necessary background information before presenting my argument, and then outlining the next steps. Canonical types Consider these two p...
1:56 AM
ジェネリックシグネチャにおけるCanonical Typeが決定不能?
Avatar
associatedtypeでprotocl自身を参照するとそうなる、のかな
Avatar
omochimetaru 8/4/2020 2:04 AM
2つのプロトコルを使って循環定義しててもなりそう
2:10 AM
プロトコル成約周りでコンパイラのバグをたくさん楽してきたけどやってもやっても新しい問題がみつかってきたけど
2:10 AM
これは背景にこの問題が決定不能だからっぽい、みたいな事を書いている
2:11 AM
We are also aware of examples where we don't manage to canonicalize types properly, causing miscompiles and crashes. We've been fixing these gradually over time, but we continue to discover more problems as we fix them. This was a strong hint that the underlying approach was not correct, which is why I spent some time thinking about the fundamentals of this problem. Indeed, we can now see that the reason we have struggled with correctness in this area of the language is that a solution is impossible in the general case.
2:18 AM
型を要素、型の中の型を参照する . オペレータを 関係 とする半群を考えると「語の問題」という既知の決定不能問題を含むことがわかる みたいな話の流れかな
2:20 AM
protocol Impossible { associatedtype A : Impossible associatedtype B : Impossible associatedtype C : Impossible associatedtype D : Impossible associatedtype E : Impossible where A.C == C.A A.D == D.A B.C == C.B B.D == D.B C.E == E.C.A D.E == E.D.B C.C.A == C.C.A.E }
2:21 AM
func isEqual<A>(_: A, _: A) -> Bool func foo<T : Impossible>(_: T) { let x: T = ... let y: T.A = ... let z: T.B.A.B = ... isEqual(y, z) }
2:21 AM
↑こんな感じで、 T: Impossible を起点に作れる型 (ABCDEの並び) が
2:22 AM
同じ型を指してるかどうか判定しないといけない (isEqualの型チェック) ときに
2:22 AM
この Impossible なケースで無理らしい
2:23 AM
令和になりました. 決定不能問題ギャラリー第12弾は「半群の語の問題」です. 有限表示半群において,生成元からなる2つの文字列が同じ元を表すかどうかは決定不能になります. https://t.co/98dOvD34X0 #たのしいけいさんろん
2:24 AM
ちょっと違うけど Tseitin半群 と同じ置換関係を持ってるように見える
Avatar
omochimetaru 8/4/2020 2:42 AM
適当に T.A.B.C.ET.E.D.C.A とか考えても
2:42 AM
確かに where を網羅的考えようとしてもどんどん伸びてって着地させらんない雰囲気がある
Avatar
おもしろい
Avatar
omochimetaru 8/4/2020 2:47 AM
もうちょっと腹落ちさせたいんだけどそのあたりググってもよくわからなかった
Avatar
Swift 固有のなにかがそうなってるのだろうか
Avatar
omochimetaru 8/4/2020 2:47 AM
確かに。ScalaとかHaskellには似たような型の機能は無いんだろうか?
Avatar
今日ずっとScalaでval/let/type/typealiasとかの微妙な違いですごい辛かった
omomuki 1
Avatar
omochimetaru 8/4/2020 2:49 AM
ww
Avatar
#swift-playgrounds から
12:57 PM
@swift-main protocol P { static func foo() } func callFoo<T>(_ v: T) { if let pProto = T.self as? P.Protocol { pProto.foo() } if let pType = T.self as? P.Type { pType.foo() } }
Avatar
swiftNightly BOT 8/4/2020 12:57 PM
exit status: 1 with stderr:<stdin>:7:9: error: static member 'foo' cannot be used on protocol metatype 'P.Protocol' pProto.foo() ^~~~~~~~~~
Avatar
.Protocolは純粋なメタタイプだからメソッド呼び出しはできない? (edited)
Avatar
omochimetaru 8/4/2020 12:58 PM
existentialはそもそもstatic methodを実行できない
Avatar
.Typeにキャストするとテーブルも付いてきて16byteになるみたい
Avatar
omochimetaru 8/4/2020 12:59 PM
existential typeはインスタンスを格納するコンテナーだから、existential type型に対するstaticなアクセスというのは理屈的におかしい
12:59 PM
openして取り出したTに対してアクセスするものなので
12:59 PM
metatypeそれ自体は「格納してるT」を持たない。
12:59 PM
概要 Swiftのprotocolには型の性質を記述する機能と、存在型として使用する機能があります。その存在型はそれ自身のprotocolに準拠しません。その理由は、スタティックメンバに関して問題が生じるからです。この記事ではそ...
12:59 PM
↑以前書いた
Avatar
それはThinなmetatypeに対する呼び出しだからじゃないですか?
Avatar
omochimetaru 8/4/2020 1:06 PM
thinなmetatype?
Avatar
thickなexistential metatypeに対する呼び出しはあると思います。
1:07 PM
thinなmetatype?
コンパイル時に決定されるがゆえにサイズが0のメタタイプ
1:07 PM
@swift-main protocol P { static func foo() } extension Int: P { static func foo() { print("Int") } } let ty: P.Type = Int.self ty.foo()
Avatar
swiftNightly BOT 8/4/2020 1:07 PM
Int
Avatar
Swiftには実行時に型情報を保持するためのType metadataという仕組みがあります。我々が頻繁に使うことはありませんが、Swiftのランタイムの動作を理解するための重要な要素です。 この記事では Type metadata...
1:09 PM
過去の自分が調べてた
Avatar
omochimetaru 8/4/2020 1:09 PM
さっきの話からすると P.Type って exsitential P の型じゃないんじゃない?
1:09 PM
@swift-main protocol P { static func foo() } extension P { static func foo() { print("static P.foo") } } func callFoo() { P.foo() }
Avatar
swiftNightly BOT 8/4/2020 1:09 PM
exit status: 1 with stderr:<stdin>:10:5: error: static member 'foo' cannot be used on protocol metatype 'P.Protocol' P.foo() ^~~~~
Avatar
omochimetaru 8/4/2020 1:10 PM
↑これはできないよ。 (edited)
Avatar
ORTの話に戻っちゃうけど、'some' return types are only available in iOS 13.0.0 or newer ←これ辛い 😇
Avatar
P.TypeがExistential metatype containerでP.Protocolがmetatypeじゃないですか?
Avatar
omochimetaru 8/4/2020 1:12 PM
@swift-main protocol P { static func foo() } extension P { static func foo() { print("static P.foo") } } extension Int: P {} func checkPE(_ a: P) { checkT(a) } func checkT<T>(_ a: T) { print(type(of: a) is P.Type) print(type(of: a) is P.Protocol) } checkPE(1)
Avatar
swiftNightly BOT 8/4/2020 1:12 PM
false true
Avatar
ORTの話に戻っちゃうけど、'some' return types are only available in iOS 13.0.0 or newer ←これ辛い 😇
iOS12を切ると幸せになります 😄
😆 1
Avatar
omochimetaru 8/4/2020 1:12 PM
それが逆なんじゃないかなと思って。 P.Protocol が existential P の型じゃない? ↑のcheckPE経由のcheckTの結果から判断した。 (edited)
Avatar
ああ、Existential Pの型はP.Protocolですね、これは名前がややこしいな
1:20 PM
P.ProtocolはExistential Pの型でP.TypeはPにconformする型のメタタイプのsupertype
Avatar
omochimetaru 8/4/2020 1:20 PM
で、Existential P の 型 P.Protocol は、 それ自体は「型のコンテナ」ではないから、真の型を内包しない。
1:21 PM
Existential P型の値は、値のコンテナだから、T型の真の値を内包する。
1:21 PM
P.TypeはPにconformする型のメタタイプのsupertype
そうだと思う。
Avatar
そうするとExistential containerとExistential metatype containerの対応がきれいになるのか
Avatar
omochimetaru 8/4/2020 1:22 PM
「Pにconformする型のメタタイプのsupertype」この概念に名前がほしいな。今まで意識してなかったモノ。
Avatar
それがExistential metatype containerですよ
Avatar
omochimetaru 8/4/2020 1:23 PM
なるほど
1:23 PM
そういうことか
Avatar
いやースッキリした
Avatar
omochimetaru 8/4/2020 1:23 PM
existential container のmetatype と exsitential metatype container は 違うものであるということか
Avatar
そうそう、それがややこしいですよね
1:24 PM
値のコンテナとメタタイプのコンテナだと思えるとキレイに見えてくる (edited)
Avatar
omochimetaru 8/4/2020 1:25 PM
メタタイプのコンテナがある事を知らなかった・・・w
Avatar
思いがけず理解が深まったw ( lovee さんありがとうございます)
😁 2
Avatar
むしろこちらこそお陰様で目が覚めたw(今日なんか一日中眠かったw
1:57 PM
そしてORTカンゼンニリカイシタ 💪
Avatar
omochimetaru 8/6/2020 6:21 AM
The urge to code won, but I limited myself to an hour. Managed to get break, continue, switch, fall through, and assert all working for my multi-statement closure inference in Swift prototype: https://t.co/bikY9NT8nA
6:22 AM
let _ = ints.map { i in let value = i + 1 return String(value) }
6:23 AM
複数文クロージャの返り値の型の推論がほぼできたらしい
Avatar
omochimetaru 8/6/2020 6:31 AM
ツイートの英語は「コードを書く衝動が勝ったけど1時間に制限した」かな? たしかにコミットがほぼ全部1時間以内にされている 早すぎ (edited)
Avatar
すげー 😯
Avatar
すごいけど、戻り値の型を推論させたいモチベが微妙にイマイチわからない 🤔
Avatar
omochimetaru 8/6/2020 8:06 AM
例えば、今までって、↓とか書けない @swift-main let foo = { let a = 1 let b = 2 return a + b + 1 }() print(foo)
Avatar
swiftNightly BOT 8/6/2020 8:06 AM
exit status: 1 with stderr:<stdin>:1:11: error: unable to infer complex closure return type; add explicit type to disambiguate let foo = { ^ () -> <#Result#> in
Avatar
omochimetaru 8/6/2020 8:06 AM
foo: Int か、 { () -> Int in のどちらかが必要。
Avatar
個人的には、それ書けない方がコードが読みやすいと思うんですよね… 🤔 複数行の型推論はコンパイラよりもむしろレビュアーのリーディングコストが高い気がします
Avatar
flatMap reduceで死にがちな型推論も多少はマシになるかなぁ
Avatar
omochimetaru 8/6/2020 8:28 AM
読みにくくなるというのは一理ありますね return String(...) とかだったら、大丈夫だと思う (edited)
8:29 AM
なんでもかんでも省略するのは良くなさそう
Avatar
multiline string literal のときの改行文字ってどうなるんですっけ?常に \n ?それとも環境によって変わる?
Avatar
試してみようとしたらバグっぽいものが見つかってしまった
7:39 AM
@swift-5.2.5 let s = """ """ s.forEach { print($0.asciiValue!) } print(s.count)
Avatar
swift52 BOT 8/7/2020 7:39 AM
0
Avatar
これは0文字であってそうな気がします
Avatar
omochimetaru 8/7/2020 7:40 AM
@swift-main let s = """ abc """ dump(s)
Avatar
swiftNightly BOT 8/7/2020 7:40 AM
- "abc"
Avatar
"""(ここはカウントされない) (ここから開始)(ここで終了) (ここもカウントされない)""" なので
Avatar
最後の改行は含まないのね
7:46 AM
変な変換掛かるの忘れてた
Avatar
The review of SE-0287 "Extend implicit member syntax to cover chains of member references" begins now and runs through August 24th, 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 l...
6:21 AM
let milky: UIColor = .white.withAlphaComponent(0.5) と書けるようにする提案です。
Avatar
omochimetaru 8/15/2020 6:23 AM
たまにそうなって型名書く事になっちゃうからたまに嬉しそう
Avatar
Kishikawa Katsumi 8/15/2020 8:56 AM
これいいよね。
Avatar
あー、これ4年前に欲しかったやつだ…
Avatar
Kishikawa Katsumi 8/19/2020 5:49 AM
https://twitter.com/SmileyKeith/status/1295904967312592896 ^ ここで言ってることって、この警告のことなのかな?
Backward matching of the unlabeled trailing closure is deprecated; label the argument with 'completion' to suppress this warning
Xcode 12b5 has SE-0286 which has turned out to be pretty brutal for us. Pro-tip: add API variations instead of fixing hundreds of call sites 🙃
Avatar
SE-0286、Nimbleでもまさに困ることになりました…… https://github.com/Quick/Nimble/issues/809
I have read CONTRIBUTING and have done my best to follow them. What did you do? I installed Xcode 12 beta 5 and tried to build our existing (test) code: it(&quot;should throw an error&quot;...
Avatar
Kishikawa Katsumi 8/20/2020 5:43 PM
むむ、互換性が壊れてる不具合があるんですね。
Avatar
omochimetaru 8/20/2020 6:15 PM
この前壊れたやつじゃん
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
https://twitter.com/johannesweiss/status/1297937217789337600 @swift-5.2.5 class One { var x: Int? init?() { return nil } deinit { print("YO") } } class Two { var x: Optional<Int> init?() { return nil } deinit { print("NO") } } _ = One() _ = Two() (edited)
@NSExceptional @steipete It’s confusing to everybody! Int? gets magically nil initialised before init. So the class is fully initialised before init (and will therefore be deinit’ed). Optional<Int> does not get this magic nil init, so the variable is uninitialised so...
Avatar
YO (edited)
Avatar
おお、ついに。
Avatar
omochimetaru 9/1/2020 2:05 AM
プロポーザルの文章がドラフトから完全に書き直されてる気がする
2:09 AM
そこに出てくる話で
2:09 AM
リテラルで頑張ると条件分岐とかだるくなるって話が出てくる
2:10 AM
このまえリテラルに分岐入れようとしてFuncB使うアイデアが出てきた話と一緒だ。
Avatar
omochimetaru 9/1/2020 2:21 AM
これって、文指向言語であるSwiftに
2:21 AM
部分的に式指向言語の力を与えるためのインターフェースと
2:21 AM
捉えると良い気がしてきた
2:22 AM
言語自体を式指向にするととっ散らかっちゃうから、型で縛った世界に部分的にそれを許す
Avatar
確かに、FB内ならif式とswitch式が実現できてますね
2:29 AM
指定した型(例えばEither)にコンパイルされる、というのも含めて良いバランスに思える
Avatar
欲を言えばwhileやforも式展開出来ると良いなと思うのだけど、難しいかな
Avatar
omochimetaru 9/1/2020 3:28 AM
できるっぽくない? buildArray(_ components: [Component]) -> Component is used to build a partial result given the partial results collected from all of the iterations of a loop.
Avatar
マジ?
3:28 AM
激アツじゃん、知らなかった
Avatar
omochimetaru 9/1/2020 3:29 AM
fastparrot 1
Avatar
この間のおもちゃのTupleリファクタリングのついでに入れておこう。 (edited)
Avatar
scalaみたいにできるようになるのかなあ
4:45 AM
alias let=val
Avatar
これ Proposal 見たとき、 for-in とかと SwiftUI の ForEach の兼ね合いはどうなるんだろうと思ったんだけど、 Identifiable なら for-in でも良いとかになるのかな? buildArrayForEach を返す? Identifiable のときだけとかできるかな。
Avatar
forを特定の型の時にForEachに展開する、と言うことが出来るようになると思います (edited)
Avatar
それはうれしいですね。 ForEach を減らせる。
6:13 AM
一方で、 Identifiable じゃないものを for-in で書いちゃうとひどいことが起こりそうですね・・・。
Avatar
ある型が複数のOptionalフィールドを持っているとき、全てnilであることを検証する良い方法ってありますか? protocol ErrorMessageProtocol { var noError: Bool } struct ErrorMessageA: ErrorMessageProtocol { var nameError: String? var valueError: String? var noError: Bool { nameError == nil && valueError == nil } } 今はこんな感じでnoErrorを書き下しているんですが、フィールドが変動すると書き漏らしが出そうで…… (edited)
Avatar
Mirror使ってOKならMirror使っちゃうのが手っ取り早そう
Avatar
実はMirror使ったこと無いのでちょっと不安なんですよね。 KeyPathIterableの早期導入が待ち望まれる。
Avatar
@t.ae プロパティの実体を Dictionary にするとかどうでしょ?
5:50 AM
「フィールドが変動すると書き漏らしが出そう」も解決できるかと。
Avatar
上の例に書いてないですがCodableになっててシリアライズするので、Dictionary だとフィールド名がぱっと見でわからないのがちょっと辛そうですね。
5:54 AM
とりあえず Mirror で書いてみます。ありがとうございました。
Avatar
Mirrorだと一般にErrorMessageProtocolに直にextension書けるので楽ができそう
Avatar
そうですね。ちょうど今それ書いてるところでした。
Avatar
omochimetaru 9/7/2020 6:12 AM
それ最近全く同じ事やったな
6:12 AM
struct ErrorProperties<T> { typealias ErrorsGetter = (T) -> [ValidationError] var getters: [ErrorsGetter] = [] init(of type: T.Type, configure: (inout ErrorProperties<T>) -> Void) { _ = type configure(&self) } mutating func add<X>(_ keyPath: KeyPath<T, Validator<X>>) { getters.append({ (target) in target[keyPath: keyPath].errors }) } mutating func add(_ keyPath: KeyPath<T, [ValidationError]>) { getters.append({ (target) in target[keyPath: keyPath] }) } func errors(of target: T) -> [ValidationError] { getters.flatMap { (getter) in getter(target) } } }
6:13 AM
Optionalじゃなくて配列だったけど struct Props: Encodable { var name: String = "" var nameErrors: [ValidationError] = [] var email: String = "" var emailErrors: [ValidationError] = [] var password: String = "" var passwordErrors: [ValidationError] = [] var passwordHints: [ValidationError] = [] var passwordConfirm: String = "" var passwordConfirmErrors: [ValidationError] = [] static let errorProperties = ErrorProperties(of: Self.self) { (c) in c.add(\.nameErrors) c.add(\.emailErrors) c.add(\.passwordErrors) c.add(\.passwordConfirmErrors) } var validationErrors: [ValidationError] { Self.errorProperties.errors(of: self) } }
6:13 AM
この実装だと取りこぼすリスクはあるけど。
6:14 AM
型のメタデータを自分で定義してることに相当すると思う。 static let errorProeprties だし。
Avatar
keyPathで全部書くのでそうですね。
12:39 PM
21日前に Typed throws のしっかりした提案が投稿されてた レスも伸びてる
Avatar
お、ちゃんと rethrows についても検討されてる。
Avatar
omochimetaru 9/14/2020 7:55 PM
レス14でジョンマッコールがrethrowsについてツッコミを入れてから
7:56 PM
残りのレス全部rethrowsの話題だ
7:56 PM
なかなか面白い
Avatar
omochimetaru 9/16/2020 7:16 AM
提案されている rethrows は、 高階関数に渡されたクロージャが返すエラーを、その高階関数も返す という仕様なんだけど
7:16 AM
従来のrethrowsは、
7:17 AM
高階関数に渡されたクロージャがエラーを返すなら、その高階関数もエラーを返す、というだけの仕様で、
7:17 AM
クロージャが返すエラーの型と、高階関数が返すエラーの型の、一致性が、「今までは無かったのに新たに制約が追加される」
7:18 AM
という下位互換の無い提案になっているから、Source breaking (過去のコードがコンパイルできなくなる)になってしまう。
7:19 AM
それで、それを回避するためのアイデアがたくさん書き込まれてた。
Avatar
これまで typed throws はなかったわけだから、高階関数に渡されたクロージャが単なる untyped な throws のときはこれまでと同じ挙動じゃダメなの?既存コードの関数を typed throws に変更するのは戻り値は covariant だからできそうだけど、 rethrows を持つ高階関数に渡しているところが contravariant だから壊れるって意味?
Avatar
omochimetaru 9/17/2020 5:56 AM
互換性の話の対象がズレてそう。
5:58 AM
まず前提として、 func loadData(file: String) throws IOError -> Data { ... } func main(files: [String]) throws IOError { // loadDataの IOError が .map から返ってきて欲しい try files.map { try loadData(file: $0) } } (edited)
5:59 AM
で、こうなるためには extension Array { func map<U>(_ f: (Element) throws -> U) rethrows -> [U] } ↑このrethrowsは、throwsのところのエラー型を投げる、としたいけど
6:03 AM
extension Array { func map<U>(_ f: (Element) throws -> U) rethrows -> [U] { var ret: [U] = [] for i in indices { let x = self[i] do { ret.append(try f(x)) } catch (error) { throw ArrayMapError(index: i, element: x, underlyingError: error) } } return ret } }
6:03 AM
↑例えばこのコードは従来はコンパイルできたけど、 rethrows を同じエラー型を投げる仕様にしてしまったら、コンパイルできなくなっちゃう。
Avatar
型をバインドする/しないをラベル付けする必要があるんですね。型パラ増やすとかになるのかな
6:14 AM
後はこういうのも気になる。 func foo(_ a: () throws -> Int, _ b: () throws -> String) rethrows これはもう有無を言わさず型を消してErrorにしちゃわないとコンパイラの負担大きくないかな、とか。
Avatar
omochimetaru 9/17/2020 6:16 AM
func map<U, E>(_ f: (Element) throws E -> U) throws E -> [U] ↑rethrowsは従来仕様のままにしておいて、伝搬スローはこうやって明示的に手書きするというアイデアもあった。
6:17 AM
E == Never のとき throws しない という扱いが入れば、これまでのrethrowsの挙動の上位互換になる。
Avatar
こうした場合、throwsが無しだとNeverが伝搬するのか。
Avatar
omochimetaru 9/17/2020 6:17 AM
そそ。 typed throws に ジェネリクスが組み合わせられるなら、rethrowsがなくてもそもそも手書きできたのだ、っていう。 (edited)
Avatar
それは正解ぽいですね
Avatar
そそ。 typed throws に ジェネリクスが組み合わせられるなら、rethrowsがなくてもそもそも手書きできたのだ、っていう。
これResultで同じようなことしてました https://twitter.com/kateinoigakukun/status/1256523271618478081?s=20
rethrowsの伝播の代わりにResultが使えることを発見した
Avatar
omochimetaru 9/17/2020 6:22 AM
Resultはその性質をもってるよね。
Avatar
あー、エラーを透過的に投げるんじゃなくて投げ直すパターンがあるのか。
Avatar
omochimetaru 9/17/2020 6:35 AM
そうなんですよ。従来のrethrowsは、エラーが「投げられる」ことだけを述べていて
6:35 AM
「同じエラーを投げる」とは言ってなかったのだ。
Avatar
なんかでもそれは微妙だな。 rethrows は意味合い的にそのまま投げるもので、別のエラーで包むのはイレギュラーな使い方な気がする。 reasync を考えると rethrows は透過的なものであることが正しそうに思う。
Avatar
omochimetaru 9/17/2020 6:37 AM
僕もそう思う。
Avatar
reasyncasync/await のプロポーザルからも外れててまだ形がないけど、 rethrows までなくなってしまうとさらに遠のきそうで嫌だな・・・。
Avatar
omochimetaru 9/17/2020 6:40 AM
// A func foo(fn: () throws -> Void) rethrows // B func foo<erased E: Error>(fn: () throws E -> Void) rethrows E // C func foo<erased E: Error>(fn: () throws E -> Void) rethrows Error
6:40 AM
>>53 で John McCallが謎文法を書き込んでる
Avatar
↓とかしたくなりそう < reasync let values = try await paths.map { try await load($0) } (edited)
Avatar
omochimetaru 9/17/2020 6:42 AM
Cが、従来のrethrowsの振る舞いを、新しい文法で形式的に書いてるとしたら、
6:42 AM
過去のコードはmigrationでこれに置き換えつつ
6:42 AM
シンプルなrethrowsは新しいそのまま投げる仕様に変更する
6:42 AM
って手順をとれば一応以降できそう。
Avatar
erased は何のためにあるの?
Avatar
omochimetaru 9/17/2020 6:44 AM
書き込みを読んでもよく理解できなかったんですが、多分、静的にはEだけどコンパイル的にはErrorってことかなあ。
6:45 AM
ABI的に?
Avatar
BerasedError が介在したいのは何なんだろう??
Avatar
omochimetaru 9/17/2020 6:45 AM
従来のエラーと同じで、ジェネリックシグネチャーを引数に取らない
6:45 AM
B is the more aggressive answer, and it would generally allow callers of higher-order operations like && to maintain more precise error types.
6:45 AM
よくわからない。Bはよりアグレッシブな案らしい。
6:46 AM
It's a nice, simple formalization of some of the type-system behavior, but it doesn't actually change the key question with rethrows, which is whether the signature of A below is equivalent to that of B or that of C: // A func foo(fn: () throws -> Void) rethrows // B func fo...
6:46 AM
ハート7個もついてる重要書き込みなのに意味がわからなくて困る
Avatar
rethrows の後ろに型を書けるようにするとして、思いつくのって↓こんなパターンだけど・・・。 // (1) func foo(fn: () throws -> Void) rethrows // (2) func foo<E: Error>(fn: () throws E -> Void) rethrows // (3) func foo(fn: () throws -> Void) rethrows FooError // (4) func foo<E: Error>(fn: () throws E -> Void) rethrows FooError (edited)
Avatar
omochimetaru 9/17/2020 6:49 AM
(3) は、fooの実装者は、 E の 生成ができないのでは?
6:49 AM
init がついてるプロトコルじゃないといかん。
Avatar
あ、間違えた。
6:50 AM
修正した。
6:51 AM
従来の map とかは (2) 、包み直す系は (3), (4)。 (edited)
Avatar
omochimetaru 9/17/2020 6:51 AM
// (5) func foo(fn: () throws -> Void) rethrows Error // (6) func foo<E: Error>(fn: () throws E -> Void) rethrows Error
6:52 AM
これを追加した上で、従来の(1)と(2)は、それぞれ(5)と(6)になってほしい。 で、これからの(1)と(2)は、
Avatar
(5), (6) は (3), (4) と同じじゃない?具体的な型を書くという意味で。
6:52 AM
ああ、そうだね。完全に同意。 < 従来の(1)と(2)は、それぞれ(5)と(6)になってほしい。
Avatar
omochimetaru 9/17/2020 6:52 AM
// (7) func foo<E: Error>(fn: () throws E -> Void) rethrows E (7)になってほしい。
Avatar
うん、そっちも同意。
6:53 AM
多分考えてること同じっぽい。
Avatar
omochimetaru 9/17/2020 6:53 AM
(1)と(2)の意味が変わって互換が壊れるのは、しょうがない!
6:53 AM
Swift6なら許される
Avatar
どうせ migration 必要なんならそれでいいよね。
6:54 AM
rethrowsrethrows Error の意味にするって方法もあるのかなぁ。透過的に投げたいなら rethrows E 。それなら互換性保てる?
6:55 AM
throwsthrows Error になるなら、それはそれで一貫性あるかも。
Avatar
omochimetaru 9/17/2020 6:55 AM
そうですね。
6:55 AM
ただ、簡単な書き方が、望ましくない方を意味しているのは
6:55 AM
年を取った言語って感じで嫌だな。
6:56 AM
新しい言語は得てしてシンプルな記法の方に、推奨挙動を込める
Avatar
ただし、 map とかは func map<T, E: Error>(_ transform: (Element) throws E -> T) rethrows E になって互換性壊れるけど。
Avatar
omochimetaru 9/17/2020 6:57 AM
結局mapは絶対その振る舞いになってほしいんですよね
Avatar
うん。
6:58 AM
簡単な書き方が、望ましくない方を意味している
↑の map みたいなときに、結局 E: Errorthrows E は書かないといけないわけで、そういう意味では throws の後ろ省略できる時点で「望ましくない方」が「簡単な書き方」になってしまってそう。
6:59 AM
func map(_ transform: (Element) throws some Error -> some Any) rethrows (edited)
6:59 AM
これはありか。
Avatar
omochimetaru 9/17/2020 6:59 AM
省略した throws と rethrows は <E> を伝搬するって意味になれば良いんじゃ?
6:59 AM
従来のthrows / rethrows は 明示的に throws Error って書いた時の挙動にする。
Avatar
それは、普通の戻り値の型の throws と意味合いが変わっちゃってるんじゃない?
7:00 AM
func foo() throws -> Foo ↑これをできなくするならいいけど・・・。
7:01 AM
↑を throws Error と同じ意味にするからには、高階関数は大抵は throws some Error -> を書くことになるんじゃない?
Avatar
omochimetaru 9/17/2020 7:02 AM
たしかにただのthrowsと高階関数にわたすクロージャのthrowsで意味が変わるのはややこしいかも。
Avatar
これって Typed Throws に関する落とし穴じゃない?高階関数において、一番簡単な書き方が望ましい書き方でなくなってしまってる。
Avatar
omochimetaru 9/17/2020 7:04 AM
func foo() throws -> Foo // ↑これが func foo() throws some Error -> Foo // ↑これの略記だという解釈だとどうだ?
Avatar
あー、 some でもダメな気がしてきた。
Avatar
「一般的な書き方が望ましい書き方ではない」 この命題はシンプルに下位互換をするかしないかと言うだけの話な気がする
7:05 AM
今までは何でもアリだったのでそこに揃えるなら望ましくならないのは当然なので。。
Avatar
今やりたいのは引数と戻り値で同じ E を使いたいことで、そうすると some じゃダメだ。
Avatar
omochimetaru 9/17/2020 7:07 AM
ああ、 some は名前引っ張れないからか。
Avatar
func foo(x: some P) -> some P これはそもそも同じ型にできない。 (edited)
7:08 AM
func foo<T: P>(x: T) -> T が必要で、同じように考えると
7:09 AM
func foo<E: Error>(fn: () throws E -> Void) throws E が正しい書き方な気がする。
Avatar
omochimetaru 9/17/2020 7:10 AM
やっぱその形が正式ですよね
Avatar
この命題はシンプルに下位互換をするかしないかと言うだけの話な気がする
これはそうかもですね。 throws の後ろを省略するのをやめれば解決。
7:10 AM
あー、話が混ざってたか。戻り値関係ないただの高階関数なら some Error でもいいのか。
7:11 AM
func foo(fn: () throws some Error -> Void)
7:11 AM
↑で some Error を使うのはありか。
7:12 AM
で、それなら一般的に throwsthrows some Error にするのか throws any Error にするのかっていう話はあり得て
7:12 AM
今は throws any Error だけど、 throws some Error にするというのも悪くないか。
Avatar
some Errorにしちゃうと、tryで別々のError Typeを指定した瞬間にコンパイルエラーですね
Avatar
はい、その場合は明示的に throws any Error を書きます。
Avatar
うーーーーーん
Avatar
omochimetaru 9/17/2020 7:14 AM
自動で共通の親の any Errorsome Error にセットされるのだとややこしいか。
Avatar
直感的には厳しそうな気がしますね
Avatar
そうですか? < 直感的には厳しそう
Avatar
自動で共通の親の any Error が some Error にセットされるのだとややこしいか。
これが可能なら受け入れられそう
Avatar
普通に -> some P するときと -> any P するときと同じじゃないですか?
Avatar
厳しそう、というのは、Swiftユーザーが受け入れられるかどうかという話です
Avatar
omochimetaru 9/17/2020 7:15 AM
あーでも、自動で共通の親は、some return でもやってないし、なしかなあ。
Avatar
some returnで出来ていないのはなぜかと言うと
Avatar
throws を戻り値の一種と考えればむしろ自然な気が。
Avatar
any P: Pが一般に宣言できてないからで
7:15 AM
Errorは any Error: Errorなので、多分出来る。
Avatar
omochimetaru 9/17/2020 7:16 AM
あー、自動erasure構成できない問題もからんでるのか。
7:16 AM
まだ any P がないから。
7:16 AM
でもどうなんだろうね、someは最適化指向的な言語機能だから、いつのまにか親にeraseされてるのは、罠になるから
7:16 AM
なんか結局コンパイラ警告が出たりしそうだな。
Avatar
そもそもTypedになるのかという仮定もあるんですが、その上で最初は許容する方向に倒れると思います。
7:18 AM
自動でsome Errorになって、any Errorも推論されうる、というのはすごく良いバランスに見える
Avatar
omochimetaru 9/17/2020 7:18 AM
ふむー
Avatar
@swift-5.3.3 struct AError: Error {} struct BError: Error {} func foo() -> some Error { Bool.random() ? AError() : BError() } print(foo())
Avatar
exit status: 1 with stderr:<stdin>:5:21: error: result values in '? :' expression have mismatching types 'AError' and 'BError' Bool.random() ? AError() : BError() ^~~~~~~~
Avatar
現状では any P: P でもできないっぽいですね。
Avatar
@swift-5.3.3 struct AError: Error {} struct BError: Error {} func foo() -> some Error { Bool.random() ? AError() as Error : BError() } print(foo())
Avatar
AError()
Avatar
omochimetaru 9/17/2020 7:21 AM
あ、なるほど。Errorで試せるのか。
Avatar
as Error を明示的に書くのであれば throws some Error でも同じことができると思います。 (edited)
Avatar
これが自動で推論されるようになればいいだけなので
7:22 AM
まだ想定されてないから実装が無いだけ、のように思える
Avatar
omochimetaru 9/17/2020 7:22 AM
まあ追加する路線はありえるね。
Avatar
うーん、 somereturn するケースで暗黙的にこれが起こるのはうれしくない気が。 (edited)
Avatar
omochimetaru 9/17/2020 7:24 AM
someのメリットは見かけの型を消すけど特殊化して性能低下しないことにあるから
7:24 AM
その挙動があると性能低下する可能性があることになって
7:25 AM
someを書くのがアンチパターンになりかねない。
7:25 AM
あ、わかった、コンパイルエラーで、
7:25 AM
result values in '? :' expression have mismatching types 'AError' and 'BError' がでたときに
7:25 AM
fix-it ボタンクリックしたら any Error に書き換わるならいいんじゃない。
Avatar
@swift-5.3.3 class Animal {} class Cat: Animal {} class Dog: Animal {} func foo() -> some Animal { Bool.random() ? Cat() : Dog() } print(foo())
Avatar
main.Dog
Avatar
これはできるんすよ
Avatar
omochimetaru 9/17/2020 7:26 AM
なにー!?
Avatar
だからprotocolについてはany P: Pが一般的に宣言出来ないから実装されてないだけ (edited)
Avatar
Kishikawa Katsumi 9/17/2020 7:26 AM
クラスならそれできるのか〜
Avatar
omochimetaru 9/17/2020 7:27 AM
親クラスあると吸い込まれるのかマジか
Avatar
いやでも一貫性として微妙な気がしてきた。
Avatar
omochimetaru 9/17/2020 7:27 AM
いやそれに警告出したくなってきたわ
Avatar
@swift-5.3.3 struct AError: Error {} func foo<E: Error>(x: E) { print(x) } foo(x: AError())
Avatar
AError()
Avatar
↑はできるわけで、
7:27 AM
それなら同じことはリバースジェネリクスでもできるべきで、
7:27 AM
Opaque Result Type でできない理由はない気がしてきた。
Avatar
@swift-5.3.3 class Animal {} class Cat: Animal {} class Dog: Animal {} func foo() -> some Any { Bool.random() ? Cat() : Dog() } print(foo())
Avatar
main.Cat
Avatar
これも出来ますね。
7:28 AM
クラスでは畳み込まれる。
Avatar
omochimetaru 9/17/2020 7:28 AM
リバースジェネリクスがreturnのところで型パラメータに代入してると考えるとそうなのか。
Avatar
↑は単に some AnyAnimal になってるだけじゃないですか?
Avatar
omochimetaru 9/17/2020 7:29 AM
some Any って響きがウケる。
Avatar
プロトコルの conformance とクラスの継承はまた別な気が。
Avatar
CatとDogがAnimalに畳み込まれることが許されるなら AErrorとBErrorがany Errorに畳み込まれるのと同じ
Avatar
some がパフォーマンスのためのものという文脈では、 CatDogAnimal として扱われても問題ないですが、 any Error は Existential が出てくるので明確にパフォーマンス上のデメリットがありますよね?
7:32 AM
つまり、 any Xxx に畳まれるのは許容しないっていう選択があり得ると思ってます。
Avatar
omochimetaru 9/17/2020 7:33 AM
問題ない
表現は確かにポインタなのでexistential containerができるよりはマシですが、なくはないです。 Catってわかってればメソッド呼び出しのdevirtualizeができうる。(vtableを無視できる)
Avatar
程度の問題って書こうとしたら書かれてた
🙂 1
Avatar
うん、 vtable を介さないってのはあるけど、
7:34 AM
でもクラスの継承は抽象型としての利用を前提としてるんじゃないのかなぁ。
Avatar
omochimetaru 9/17/2020 7:34 AM
それはそうかも。
Avatar
プロトコルはそうではないという意味で違うと思う。
Avatar
omochimetaru 9/17/2020 7:35 AM
structがexistentialになるのはSwiftプログラマに取っての重みが違う。
Avatar
程度問題の程度が、 1 が 2 になるのと 1 が 100 になるのくらいの違いがありそうな気が。
Avatar
some Xでany Xへの変換を許容しなかった場合、結果どうなるかというと
7:36 AM
return typeにany Xが使われてもっと悪い方向に向かうので
7:37 AM
まあ警告出してもいいけど許容するしかないんじゃないの。。。とは思いますね
Avatar
-> some P で暗黙的に existential 返すくらいなら、明示的に -> any P した方がいいんじゃないですか?
Avatar
私はその理屈は理解できますけど、一般Swiftプログラマーに理解しろ、というのはかなり無理筋だと思っていて
Avatar
その違いを理解せずに適当に some P, any P を使うのはヤバい気が・・・。
Avatar
基本的にはsome Pを使えばそれなりに効率よく動く、どうしようもない場合だけany Pにする、みたいなプラクティスに落としておくのがバランスが良い気がしていて
7:40 AM
リバースジェネリクスみたいな局所的な場面に閉じてるんだったら、まあ高難易度でもいいんですけど
Avatar
はい、それが現実的だと思います。
Avatar
throws/rethrowsみたいな凄い広いユースケースでそれが露出してしまうのはかなり厳しい
7:41 AM
デフォルトでsome Errorに倒して、暗黙的にany Errorになりうるぐらいのバランスじゃないと、利用者側のフラストレーションが大変なことになるんじゃないかと
Avatar
omochimetaru 9/17/2020 7:43 AM
うーんたしかに、 素人はガバガバ throws 使っとけって気もするな
Avatar
うーん、 throws も一種類しか投げてなければコンパイルエラーにならないので、エラーになったら throws any Error にするので良い気も?
Avatar
omochimetaru 9/17/2020 7:43 AM
Javaの検査例外が嫌われたことを思うと・・・
Avatar
高階関数書くような人はきちんと理解して throws some Error を書けと?
7:45 AM
map とかは結局ジェネリクスになるしなぁ。
Avatar
や、じゃなくて
7:45 AM
「throws some Errorがデフォルトだが、素人が使ってもエラーが出ない」を満たす必要があって
7:46 AM
これを満たしておけばかなり高確率で高性能だし、ガバってもany Errorでカバーできる
Avatar
omochimetaru 9/17/2020 7:46 AM
僕は some に対する親消去は良くないと思うので、 無印throwsは throws any Error にしておいて
7:46 AM
パフォーマンスや型システムがちゃんとわかってる人が map とかを <E> で書くのが
7:46 AM
やっぱりバランスが良い気がしてきた。
Avatar
そうすると世の大半のthrowsは全部Existentialになっちゃうけど
7:47 AM
まあそれはそれで今まで通りか
Avatar
ライブラリでは Typed Throws を、アプリでは Untyped Throws をという棲み分けならそれでもいいのかなぁ。
Avatar
some Errorデフォルトなら、かなりの確率でtypedに倒せるっていう旨味があるんで
Avatar
foo(fn: () throws -> Void) // vs foo(fn: () throws some Error -> Void) foo<E: Error>(fn: () throws E -> Void)
Avatar
あー
7:50 AM
因みにsome Errorになりうるのはクロージャ側じゃなくて関数側
Avatar
せめて Opaque Argument Type がないときつい気がする・・・。
Avatar
func foo() throws some Error func bar<E: Error>(_ fn: () throws E -> Void)
7:50 AM
これが正しい
Avatar
あ、そういうことじゃなくて、一般論として func foo() throwsfunc foo() throws some Error func foo() throws any Error のどちらになるのかという話があって、
Avatar
OATが導入されてGenericsをsomeで書けるようになるかつ、 throws無明記がsomeに倒れれば
7:52 AM
今ある全てのthrowsが修正無く(そこそこの確率で)高効率に動くようになる、というのは結構魅力的ですね
Avatar
そこで any Error をとった場合は、これまで bar(fn: () throws -> Void) と書いてたものについて、望ましい書き方は foo(fn: () throws some Error -> Void) または foo<E: Error>(fn: () throws E -> Void) になると。
Avatar
そうですね。なのでsomeに倒れたほうがいいんじゃない?(その上で内側で発生するany Errorも許容すれば、下位互換も保てる) という議論です
7:54 AM
下位互換を保つというのは、ただ既存のプログラムの挙動を保証するだけではなく言語のアップデートをキャッチアップしなくてもPGがそのまま使い続けられる、ということも含めるので (edited)
Avatar
any Error: Error を考えると、高階関数の引数が throws any Error であってうれしいケースはない気がするから、無印 throwsany Error に倒してしまうと高階関数が常に辛いことになる。
7:55 AM
一方で今のまま throws some Error に倒してしまうと一般人が異なる型を throw しようとして辛い目にあう。
Avatar
omochimetaru 9/17/2020 7:55 AM
既存実装を性能が良い方に倒したいというのはあるか。 (edited)
Avatar
折衷案として tarunon さんのいう some Errorany Error を投げるという手がある。
Avatar
omochimetaru 9/17/2020 7:55 AM
someに倒して ミスマッチしてるケースはエラーもしくはmigrationでanyに直す だと、自分的にはアリかな。 (edited)
Avatar
しかも、それはジェネリクスの <E: Error> に対して any Error を渡せる今の仕様と一貫性がある。
7:56 AM
ただし、 -> some P してるのみミスって existential 返してしまっているケースを検出できなくなる。
7:57 AM
あー、 throws some Error についてだけ暗黙的に any Error になるという形で一般的な戻り値と区別すれば現実的な落とし所になるのかな?
Avatar
omochimetaru 9/17/2020 7:58 AM
まあそもそもエラーはマイナーパスなので性能最適化いらない説とかありそう。
Avatar
ミスって existential 返してしまっている
これはミスではないとは思うけど
7:59 AM
どちらかというと、some Pって書いてるところに「お前これany Pって書けるやで」っていうwarningをfix-itで出してあげるぐらいで親切っぽい
7:59 AM
それが可能ならその仕組をthrowsに転用したらまー大体平和なんじゃないかな
Avatar
-> some Animalreturn isFoo ? Cat() : Dog() してるとかはエラーにしてほしい気がしますね。
Avatar
いや〜〜〜〜〜
Avatar
警告でいいのかなぁ・・・。
Avatar
警告+any Animalへのfixitで良さそう
Avatar
まあやりたいケースはあるかぁ。
Avatar
例えばOptionalとかを渡したら警告でるのと一緒で、エラーではないですね
Avatar
some から any になると API の型が変化してしまうけど、それを避けたいケースはあるかも?
Avatar
因みに
8:03 AM
これが可能である条件は any P: P の場合だけで
8:03 AM
APIの型としては共変性がある状態で狭い方になってるだけなんで
8:03 AM
互換性の問題が発生しません。
Avatar
そうか、 any P: P ができるようになっても、それが opt in である限り問題にならないわけですね。
8:37 AM
その上で警告はかなり良いバランスな気がしてきました。
8:40 AM
まとめると↓でしょうか。高階関数の問題も解決されますね。
  • 無印 throwsthrows some Error の意味にする
  • any Error: Error なので、複数種のエラーを throw すると any Error として throw されて警告が出る
(edited)
8:42 AM
こういう意見がフォーラムに出てないなら一言書いておいた方が良さそうだ。今晩でも書いてみようかな。
Avatar
omochimetaru 9/17/2020 8:43 AM
多分出てなかったと思う。
8:44 AM
途中の John McCallの書き込みと、 xwu さんの >>143 がなんかまとまってるっぽい雰囲気になってるからこれは読んでおくと良いかも
👌 1
Avatar
Let me show an option though I am not sure if it is good. Currently, it is discussed that the following two are equivalent. func foo() throws func foo() throws Error In the context of "Improving the UI of generics", it can be written as shown below. func foo() throws any E...
👏 1
5:38 PM
やっぱ英語書くの時間かかりすぎる・・・。
Avatar
any Errorが文脈すっ飛んでいきなり出てきてるように見えます👀
Avatar
逆に考えるのです... 日本語が速すぎるのです...
😂 1
Avatar
omochimetaru 9/17/2020 5:39 PM
簡潔だ
5:40 PM
In the context of "Improving the UI of generics",
↑これを受けてるから文脈は繋がってると思うよ
Avatar
ああ、リンク先にあった
Avatar
まだ 3 人も起きてたw (edited)
Avatar
omochimetaru 9/17/2020 5:40 PM
これを読んでないとわからんと思うけどこれは最近の必読テキストだからええやろ
Avatar
これ前提の議論がされてる感じなんすか
Avatar
omochimetaru 9/17/2020 5:41 PM
いや、このスレッドではany X とか some Xは初出かも
Avatar
このsome使うのが良いんじゃないか、は
5:42 PM
かなり多くの議論の上に成り立つから日本語でも難しそう
Avatar
Opaque Result Type は実際に導入されてて、 "Improving the UI of generics" はその前提になったドキュメントだからここにいる人は知ってる前提でいいかなと。知らない人はリンク先読めるし。
5:42 PM
今日も相当話しましたしね < 日本語でも難しそう
5:44 PM
そういえば、これ書く過程で、 func map<T, E: Error>(_ transform: (Element) throws E -> T) throws E -> [T] がいいとは限らないことに気付いた。
5:44 PM
transform が複数の種類のエラーを throw するかもしれない。 (edited)
Avatar
その場合はany Errorだから問題ないのでは
Avatar
はい、それ前提なら問題ないんですが
5:45 PM
昼間はそれ前提でなくても↑にしたいみたいな話をしてたので。
Avatar
ログ見返してたけどどこで指摘してるのかわかんなかった
5:52 PM
そもそもthrows rethrowsではクロージャ側だからORTじゃなくて普通にgenericsになるはず
5:53 PM
で、ORTでany Errorを推論されたくないという結論のもと、throws rethrowsでも封印する仮定ならthrows rethrowsでGenericsを使うのが良いとは限らない、という話? (edited)
6:24 PM
throw AErrorthrow BError があるときに Eany Error として解釈してくれるならいいんですけど、それができないなら func map<T, E: Error>(_ transform: (Element) throws E -> T) throws E -> [T] ではなく func map<T>(_ transform: (Element) throws -> T) rethrows -> [T] でないと、これまでできたことができなくなるなと。
Avatar
any Errorを許容するのが丸いのではw
6:25 PM
割と僕はそれも含めて一貫した挙動が良いと考えています
Avatar
ですね。 any Error が良さそう。
Avatar
これもしかしてORTへの言及って初めてですかね?
Avatar
とりあえず投稿前に "some" と "opaque" で検索してもこのスレッドではそれらしきものはヒットしませんでした。
Avatar
omochimetaru 9/22/2020 2:30 AM
It looks like concurrency support in Swift 6+ is going to be quite powerful, and quite possibly not limited to just async/await. I'm starting to see more and more references to actors in toolchain PRs. OTOH, this could be a purely internal thing. https://t.co/Vlz3GIfQeL
2:30 AM
新しいキーワードにactorって語が含まれてる
Avatar
なんか最近Rubyでも見たワードですね
5:13 AM
Ractorだったかな
Avatar
Akkaですね
5:30 AM
Akka is a toolkit for building highly concurrent, distributed, and resilient message-driven applications for Java and Scala.
5:31 AM
actorモデル自体が発表されたのは1970年代とかなんでかなり古典
Avatar
Actor については Concurrency Manifesto の中で async/await と同時に当初から言及されてますね。 https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782#part-2-actors-eliminating-shared-mutable-state
2:48 PM
僕は actor そのものもですが、 Part 3 で述べられている "Reliability through fault isolation" に注目しています。 https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782#part-3-reliability-through-fault-isolation
2:50 PM
これによって Logic Failure のハンドリングが可能になるかもしれません。
2:51 PM
actor を取り入れていることで一番有名な言語は Erlang だと思います。 (edited)
2:54 PM
Erlang の書籍で有名なのは、 Erlang の設計者自身が書いた↓と、 https://www.amazon.co.jp/dp/B079YZC22H
AmazonでJoeArmstrong, 榊原一矢のプログラミングErlang。アマゾンならポイント還元本が多数。一度購入いただいた電子書籍は、KindleおよびFire端末、スマートフォンやタブレットなど、様々な端末でもお楽しみいただけます。
2:54 PM
それより新しく数年前に話題になった↓あたりがあります。 https://www.amazon.co.jp/dp/B00MLUGZIS
AmazonでFredHebert, 山口能迪のすごいErlangゆかいに学ぼう!。アマゾンならポイント還元本が多数。一度購入いただいた電子書籍は、KindleおよびFire端末、スマートフォンやタブレットなど、様々な端末でもお楽しみいただけます。
Avatar
omochimetaru 9/22/2020 2:57 PM
まだasync awaitが入ってないのに、actorの、しかもそれのisolationとやらが出てきてるのが気になります
Avatar
async/await はしっかりやってほしいね。 Swift 6 で入らなかったらかなり辛い・・・。
Avatar
omochimetaru 9/22/2020 3:00 PM
そうですね。server sideでfutureでガシガシ書いてると、やっぱり同期コードと比べてしんどいです。
Avatar
あと個人的になんとか any Protocol を Swift 6 に入れてほしいかな。そうじゃないと any はかなりきつくなりそう・・・。
3:02 PM
破壊的変更だし。
3:02 PM
とりあえず現状の互換性維持&警告という形ででもいいから。
Avatar
omochimetaru 9/22/2020 3:03 PM
早く欲しいけどくるかなあ、、
Avatar
リバースジェネリクスとか some の拡張とかは後からでも何とでもできるけど、 any だけは Swift 6 で入れないと入れ時がなくなる気がしてる。
3:05 PM
実装は難しくないと思うけど、破壊的変更なのがネックで、それ単体で利便性もわかりづらいんよね。 Joe Groff のドキュメントがあるとはいえ。
Avatar
actor !!
Avatar
omochimetaru 9/23/2020 5:35 PM
swift 9
5:36 PM
数週間で並行処理について出てくるらしい
5:29 AM
これは嬉しい
5:30 AM
Multi-platform not Cross-platform
5:30 AM
おもしろい
Avatar
omochimetaru 9/26/2020 5:37 AM
DarwinとGLibCのブリッジとかエラーのthrows化とか
5:38 AM
まずそこからになるからめんどくさかったんだよね。
5:39 AM
@_alwaysEmitIntoClient public static var ioError: Errno { Errno(_EIO) } @_alwaysEmitIntoClient @available(*, unavailable, renamed: "ioError") public static var EIO: Errno { ioError }
Avatar
もうこれ書かなくて良いのか #if canImport(Darwin) import Darwin #elseif canImport(Glibc) import Glibc #endif
Avatar
omochimetaru 9/26/2020 5:39 AM
↑最初から死んだAPI用意してあるw
5:39 AM
調べてでてくるのは EIO の方だから一度補完で出させてから きれいな名前の方に誘導してる
5:40 AM
Contribute to apple/swift-system development by creating an account on GitHub.
Avatar
えらい
Avatar
yutailang0119 9/26/2020 5:40 AM
かしこい
Avatar
omochimetaru 9/26/2020 5:43 AM
// @available(macOS 10.16, iOS 14.0, watchOS 7.0, tvOS 14.0, *) internal func valueOrErrno<I: FixedWidthInteger>( retryOnInterrupt: Bool, _ f: () -> I ) -> Result<I, Errno> { repeat { switch valueOrErrno(f()) { case .success(let r): return .success(r) case .failure(let err): guard retryOnInterrupt && err == .interrupted else { return .failure(err) } break } } while true }
5:43 AM
retryOnInterruptの実装はこのユーティリティで共通化してあるみたい。
5:44 AM
シグナル割り込みって普通にエラー飛べば良いと思ってたんだけどこのライブラリではデフォルトは再試行らしい。
Avatar
大抵の場合リトライするからなぁ
Avatar
omochimetaru 9/26/2020 5:44 AM
そうなのか・・・
Avatar
雑なハンドリングしかしないから分からない…
Avatar
omochimetaru 9/26/2020 5:45 AM
終了はアプリ側で自力のシグナルハンドラを書いて明示的にやるのがモダンなのか?
5:45 AM
まあ C-c でなくとも C-z とか考えるとそうするしかないんかな
Avatar
TSCのシステムコールユーティリティは大体↑みたいな実装になってる
Avatar
omochimetaru 9/26/2020 5:46 AM
そうなんだ〜
5:47 AM
今後はswift-nioとswift-pm(tsc)の下請けをこれに変えるって書いてある
5:50 AM
FilePath型はnull terminatedで、ExpressibleByStringLiteralだけど、 (edited)
5:51 AM
文字列操作APIは持ってないみたい
5:52 AM
path component の結合ぐらいはあったらよさそうだけど
5:53 AM
いまんところ FILE 系しか無いみたいだ 今後が楽しみ
Avatar
このくらいのインターフェースならWasi実装も入れられそう
Avatar
omochimetaru 9/26/2020 5:54 AM
WASIならほぼ自明に対応実装くっつけられそうだね
👍 1
Avatar
Contribute to apple/swift-atomics development by creating an account on GitHub.
Avatar
基本的には SE-0282 の初版でレビューされてたものですね https://forums.swift.org/t/se-0282-low-level-atomic-operations/35382
The review of SE-0282: Low-Level Atomic Operations begins now and runs through April 24, 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...
12:48 AM
レビューの結果 SE-0282 自体はメモリーモデルの明確化にフォーカスして再レビュー、それを元に
The Swift project itself plans to develop one of these packages.
としていたものの成果です
(edited)
Avatar
norio_nomura 10/2/2020 3:42 AM
libclangのラッパーなのね。
Avatar
linuxでテストをビルド出来ないな。
Avatar
norio_nomura 10/6/2020 3:26 AM
ビルド時間比較のために4行ほど修正してSwift 5.2でビルドできる様にしたのだけど、PR受け入れてもらえるのだろうか?>swift-atomics (edited)
Avatar
Linux上でSwiftPMのバグっぽいの前から気になってたんですが再現作ってみました。だれか確認してもらえますか&既知のバグだったら教えてもらえますか。 https://github.com/t-ae/SPMDeps
Contribute to t-ae/SPMDeps development by creating an account on GitHub.
2:43 AM
概要はREADMEに書いてますが、特定条件でswift package resolve の結果がおかしいというものです。
Avatar
norio_nomura 10/7/2020 4:39 AM
0.0.1をチェックアウトしてswift package resolveをした時点で、.build/workspace-state.jsonにSPMDepLibの0.0.1使っているという情報が保存されます。 0.0.2をチェックアウトしてswift package resolveすると、ワーキングコピーよりもworkspace-state.jsonの情報を優先して、Package.resolvedのSPMDepLibを0.0.1に戻すのだと思います。
Avatar
swift package reset したら正しく解決するようになるので何かキャッシュされてるとは思ってたのですがそこにあるんですね。 予期する挙動とずれていてバグになるんじゃないかと思うのですがどうでしょう?swift package reset すると全部再フェッチ&ビルドが必要なのも気になりますし。
Avatar
norio_nomura 10/7/2020 5:17 AM
swift package --force-resolved-versions resolveするとPackage.resolvedを基にworkspace-state.jsonを更新してくれるみたいなので、その後swift package resolveすれば再フェッチは回避出来そう。
5:18 AM
--force-resolved-versionsというオプションがある時点で、この様な場面は過去に問題として挙がってそう。
👀 1
Avatar
おお、そんなオプションが! vaporプロジェクトmacで開発してubuntuに展開するんですが、依存変わるたびにこれで悩まされてたので使わせてもらいます。 教えていただいてありがとうございました🙇‍♂️
👍 1
Avatar
@swift-5.3.3 let a: [Int?] = [nil] let b = a.randomElement()! print(type(of: b)) if case let c as Int = b { print("OK", c) }
Avatar
Optional<Int>stderr:<stdin>:5:15: warning: 'as' test is always true if case let c as Int = b { print("OK", c) } ^
Avatar
これなんでalways trueっていってくるんだろ?
Avatar
bの型がIntだから
1:23 PM
あ、ちがうか
1:24 PM
bはInt??にびっくり付けてInt?か
1:25 PM
バグっぽい
Avatar
swift-4.1.3 botでも同じだからかなり見過ごされてきてる
Avatar
@swift-5.3.3 let a: Optional<Int> = 1 print(a is Int) print(Optional<Int>.self is Int.Type) (edited)
Avatar
true falsestderr:<stdin>:2:9: warning: checking a value with optional type 'Optional<Int>' against dynamic type 'Int' succeeds whenever the value is non-nil; did you mean to use '!= nil'? print(a is Int) ~ ^~~~~~ != nil <stdin>:3:26: warning: cast from 'Optional<Int>.Type' to unrelated type 'Int.Type' always fails print(Optional<Int>.self is Int.Type) ~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~ (edited)
Avatar
型的にはInt? is Intはfalseだけど、Optionalの特別扱いで中身を見ている?
1:31 PM
あ、nilに対してalways trueが出てるのか。誤読してた
Avatar
最適化逃れコードが入ってて分かりづらかったですね
1:48 PM
@swift-5.3.3 let a:Int? = nil if case let b as Int = a { print("OK", b) }
Avatar
stderr:<stdin>:2:15: warning: 'as' test is always true if case let b as Int = a { print("OK", b) } ^
Avatar
switchだと
2:04 PM
@swift-5.3.3 let a: Int? = 1 switch a { case let b as Int: print("OK", b) }
Avatar
exit status: 1 with stderr:<stdin>:3:12: warning: 'as' test is always true case let b as Int: print("OK", b) ^ <stdin>:2:1: error: switch must be exhaustive switch a { ^ <stdin>:2:1: note: add missing case: '.none' switch a { ^ <stdin>:2:1: note: add missing case: '.some(_)' switch a { ^
Avatar
.someも足せっていってきますね
Avatar
Taihei Mishima 10/15/2020 5:08 AM
[質問です] 秘匿情報をKeychainに保持する時に bundleId: userId: accsessTokenなど: value のように保存したい場合 kSecAttrService: ???: kSecAttrAccount: value という感じになるのかなと思っているのですが ??? の部分に入れるのは何がいいのでしょうか. kSecAttrGeneric なのかなーと眺めているのですが... https://developer.apple.com/documentation/security/keychain_services/keychain_items/item_return_result_keys?language=objc (edited)
Avatar
Kishikawa Katsumi 10/15/2020 7:31 AM
Keychain APIは「キー: 値」の形で保存するものなので階層を持つようような構造を保存したい場合は値の部分をまるっとその構造にする必要があります。 今だったらCodableに対応させてJSONエンコードして保存する、などが簡単じゃないでしょうか。
Avatar
Taihei Mishima 10/15/2020 7:40 AM
ご回答ありがとうございます! 質問の仕方が悪く申し訳ないのですが, 階層構造を持ちたいと言うよりは bundleId && userId && accessToken みたいにできると嬉しいなと思っています. Kishikawaさんの作成されているKeychainAccessの let keychain = KeychainAccess(service: bundleId) keychain.set('hogehoge', key: "accessToken") let token = try? keychain.get("accessToken") // "hogehoge" という処理は bundleId && accessToken と言う条件で取得をできているのではないかと思っています. この取得の条件に userId を付加できないかなと考えているのですが, これは難しいというか, 使い方としてまちがっていますかね... (edited)
Avatar
Kishikawa Katsumi 10/15/2020 7:47 AM
おっしゃられているようにクエリに使えるAttributeを代用するのはアリと思います。 が、まあ意外にないので素直には難しいですね。 キー : 値 として "\(bundleId)\(serId)" : accessToken のように連結するか bundleId : userId userId : accessToken のように辿るようにするか、かと思います。
Avatar
Taihei Mishima 10/15/2020 7:50 AM
なるほど, 素直に実装するにはちょっと難しいということなんですね. ご丁寧にありがとうございます!
7:50 AM
"\(bundleId)\(serId)" : accessToken 一旦こっちでやってみようと思います.
Avatar
Kishikawa Katsumi 10/15/2020 7:52 AM
単純に連結すると重複ができることがあるので両方で使われない文字を間に挟むとかするとだいたいうまくいくと思います。 "\(bundleId)$\(serId)"
Avatar
Taihei Mishima 10/15/2020 7:56 AM
たしかに重複の可能性ありますね. ありがとうございます, とても参考になりますmm
Avatar
Swift の Documentation Comment (↓のような)についての公式ドキュメントってありますっけ? https://github.com/apple/swift/blob/main/stdlib/public/core/Result.swift#L23-L40 ↓とか? Latest Commit が 2015 年なのが厳しそう・・・。 https://github.com/apple/swift/blob/aa3e5904f8ba8bf9ae06d96946774d171074f6e5/docs/DocumentationComments.md
Avatar
そのmdしか見たことないです
2:05 AM
そういえばちゃんとテキストが無いの変ですね。
Avatar
どこかで見たな〜〜と思って今必死に探したらそれっぽいのが見つかりました。 https://developer.apple.com/library/archive/documentation/Xcode/Reference/xcode_markup_formatting_ref/index.html#//apple_ref/doc/uid/TP40016497-CH2-SW1
Describes the markup formatting language used for creating rich playgrounds, documenting swift code, and adding developer symbols to QuickHelp.
Avatar
DocumentationComments.mdの末尾にそれへのリンクがありますよ。
Avatar
ホントだ 👀
Avatar
おお。
Avatar
/// 主体なのはただの慣習ですが?
Avatar
スラッシュ3つにするとxcodeでフォントが変わりますよね
Avatar
はい。
2:15 AM
ブロックコメントにする場合は↓が紹介されてるけど、 /// で統一するのは慣習なのかなと。 /** */ https://developer.apple.com/library/archive/documentation/Xcode/Reference/xcode_markup_formatting_ref/ComentBlock.html#//apple_ref/doc/uid/TP40016497-CH103-SW1
Describes the markup formatting language used for creating rich playgrounds, documenting swift code, and adding developer symbols to QuickHelp.
2:16 AM
「xcodeでフォントが変わ」るのは /** も同じっぽいので。
Avatar
///の方がインデントを統一しやすいんじゃないかな。 (edited)
Avatar
/// は何行にもわたると流石にうざい感じがある
1:48 AM
/** *//// はXcodeでは同じ扱いかなあ
1:48 AM
ドキュメントコメントできない箇所につかうとなんか変なことになった気がする... のはswiftdocかsourcekittenの仕様だったか...
Avatar
Hello Swift Community, The second round of review for SE-0289 "Result Builders" ran from September 24 through October 1, 2020. You can find the review thread here. The first round of review for SE-0289 "Function Builders" ran from August 31 through September 14, 2020 and yo...
2:21 PM
Result Builder で決まった
👏 4
Avatar
Tuples Conform to Equatable, Comparable, and Hashable マージされてました https://github.com/apple/swift/pull/28833
From: https://forums.swift.org/t/hacking-equatable-conformance-on-void/25975 The tests right now are kind of lackluster, what else can I be testing with this? What else can be improved upon in this...
Avatar
Kishikawa Katsumi 10/27/2020 6:40 AM
いいやん。
Avatar
インラインアセンブリもりもり実装でwasm向けに直すのがすごく大変
😅 2
😫 1
Avatar
VoidがEquatableになるぞヤッター!
Avatar
インラインアセンブリ
なんでそんなのいるんだ?
Avatar
stdlibにタプル向けのプロトコルコンフォーマンス達を事前に定義しておかないといけないんですけど、プロトコルコンフォーマンスはPC相対を含んだ構造なので普通のC++だと表現できないから?
Avatar
Kishikawa Katsumi 10/27/2020 6:44 AM
どれのことやろ、と思って探してたけど初期状態だと隠れてた https://github.com/apple/swift/pull/28833/files#diff-c289d2fa8030a8b0648018ab48d060bb32554aa01b96399c406702089ef0033c この辺が実装か。
Avatar
C++ソースをコンパイルするだけでオブジェクトファイルの中にメタ情報がレイアウトされてるようにしたいってこと? (edited)
Avatar
そうですそうです
Avatar
BuiltinProtocolConformances.cpp
6:46 AM
6:47 AM
たしかにC++の定数定義じゃ記述できない・・・
Avatar
Kishikawa Katsumi 10/27/2020 6:47 AM
#if defined(__ELF__) " .type __swift_tupleEquatable_private, @object\n" " .local __swift_tupleEquatable_private\n" " .comm __swift_tupleEquatable_private, 128, 16\n" " .protected " TUPLE_EQUATABLE_CONF "\n" " .type " TUPLE_EQUATABLE_CONF ", @object\n" " .section .rodata\n" #elif defined(__MACH__) " .zerofill __DATA, __bss, __swift_tupleEquatable_private, 128, 4\n" " .section __TEXT, __const\n" #elif defined(_WIN32) " .lcomm __swift_tupleEquatable_private, 128, 16\n" " .section .rdata, \"dr\"\n" こういう感じだからWebAssembly向けの実装を足さないといけないのか。
Avatar
初期構築関数みたいなの作ってもヒープアロケートになっちゃうし、たしかに・・・
6:48 AM
コンパイラでしか無さそうなニーズと深いハックだなあ・・
Avatar
__asm__ に書けるアセンブリコードのドキュメントが見当たらなくて、LLVMのテストケースを見ながらせっせと書いてます (edited)
Avatar
そもそもwasmターゲットのときにもちゃんと動くんかしら
6:51 AM
__asm__ 文。
Avatar
動くんですよそれが
Avatar
なんか関数とかもアドレスじゃなくてテーブルインデックスとかで管理されるよね?
6:53 AM
概念モデルがうまくマッピングできるもんなのか
Avatar
関数アドレスがテーブルインデックスとして降下していればいい感じに動くんじゃないですかね
7:02 AM
関数アドレスの相対位置からデータアドレスを得るとか、逆にデータアドレスを足し引きして関数アドレスを得る、みたいなことを意図的にできないようにしているんだったかな。
Avatar
関数テーブルは別として、データアドレス空間は普通にリニアなの?
Avatar
そうですね、線形メモリです (edited)
Avatar
それなら同じようにコンパイルできそうだなあ。なるほど。
Avatar
File describing the roadmap for introduction of concurrency. Living document expected to link to various proposals and cover features as they are designed.
5:18 PM
並行処理についての文書
5:19 PM
asyncやactorについて。
Avatar
おおお、ついに
5:21 PM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
5:25 PM
Unlike a manifesto, which might describe multiple possible directions and in some cases unlikely directions, this document describes a single intended plan for tackling concurrency in Swift.
5:31 PM
なるほど。このドキュメントが短い理由↓
As a roadmap, this document does not go into the same level of detail as will those proposals. It also discusses features for the second phase, but detailed proposals for this area will wait until after the first phase is better defined.
Avatar
Hello all, One of the main parts of the Swift Concurrency model is actors, which provide a mechanism for isolating state in concurrent programs to eliminate data races. This proposal introduces actors and actor isolation into Swift. It is part of the Swift Concurrency effort ...
👀 1
Avatar
おおお
Avatar
これは読むのが忙しくなりそう。
Avatar
github の md file と forums の投稿と、関係性がよくわかってない
6:24 PM
コミュニティの全体図とリソースと誰がリードしてるのかとか図があるといいなあ
Avatar
mdファイルはAppleのチームの人達が勝手に追加したりしてるやつで、今後の方針とか開発者向けのガイドとか裏技とかいろいろある フォーラムはコミュニティと意見交換したり、evolutionプロセスをすすめるための場所
Avatar
mdファイルはAppleのチームの人達が勝手に追加したりしてるやつ
7:10 PM
まじかw
Avatar
いろいろ読んだ Actorっていうのは要するに外からはasyncなメソッドしか呼び出せない特殊なクラスなんだな
Avatar
masterが全部mainになっててめちゃくちゃになった...
7:54 PM
辛い
Avatar
外部から呼ぶ場合のキューへの投入も自動か。
4:32 AM
スレッドセーフなクラスを作るときに手書きしてるパターンを自動でやってくれるという感じだから普通に便利そう
Avatar
こういうマルチスレッドなコンポーネントを作る時って、キャンセルや停止のAPIだけは同期的にして、呼び出しの後でコールバックが起きないようにするのがパターンだけど
5:39 AM
アクターだとそういう停止も組めないのはどうすればいいんだろう?
5:40 AM
一回普通のクラスでラップするといいのかな。
Avatar
actor class PlayerRefreshControler { var players: [String] = [] var gameSession: GameSession func refreshPlayers() async { ... } }
9:36 AM
↑この Roadmap に載ってるクラス、プロパティは private じゃなくていいの?
9:36 AM
queue.sync が挟まれるのかな?
Avatar
じゃなくていいとは?
Avatar
actor class のメソッドやプロパティがあるキューからのみアクセスされることが保証されるとして、 async メソッドは非同期にそれが行えるけど、それができないプロパティの場合はどうなるの?全部 sync 相当になる?
9:43 AM
まだ actor の Proposal は読んでなくて Roadmap 読んでるところなので、
Avatar
そもそもアクセスできないです
Avatar
Proposal には書いてあるのかも。
Avatar
アクターのプロパティはそのアクターのメソッドの中でselfのものしかさわれない
Avatar
そうなのか。 Proposal も読んでみます。
Avatar
9:54 AM
スレがいっぱい
Avatar
First Phase までしか読んでなかったけど "Actor Isolation and The Second Phase" 以降に色々書いてあった。
Avatar
セカンドフェーズはソースブレーキングなの面白そうですね
10:01 AM
func makeDinner() async throws -> Meal { async let veggies = try chopVegetables() async let meat = marinateMeat() async let oven = try preheatOven(temperature: 350) let dish = Dish(ingredients: await [veggies, meat]) return await try oven.cook(dish, duration: .hours(3)) }
10:02 AM
structured concurrencyなんだこりゃ
10:02 AM
async letはパラレルになるらしい
Avatar
あー、let自体がasyncだからawaitしてから使う気持ちなのか
10:15 AM
nurseryって保育所?は子タスクを閉じ込めてるアナロジーか。へー
Avatar
asyncawaitのproposalはラトナー版から全く書き直されてますね
4:48 PM
beginAsyncとかも出てこないような?
4:49 PM
元々のやつは実行系についてはノータッチだったけど、
4:49 PM
アクターのメソッドを呼び出す時にはアクターの型のenqueueメソッドが差し込まれるので
4:50 PM
asyncを呼び出すところで実行系が変わる仕組みを差し込めるようだ
4:50 PM
それで呼び出しから戻ったら元のexecuterで続きをやるらしい
Avatar
まだ読んでないけど、 beginAsync はなくなって @asyncHandler になったんじゃないの?この前の waiwai で見てた PR の感じだと。
Avatar
async proposalにその辺の話が無いきがする?
5:26 PM
structuredの方に Task.runDetached というのがあったりしますね
5:27 PM
ロードマップのほうに
5:27 PM
Async handlers introduces the ability to declare a synchronous actor function as an asynchronous handler. These functions behave externally like a synchronous function, but internally are handled like an asynchronous function. This allows traditional “notification” methods, such as those on UITableViewDelegate, to perform asynchronous operations without cumbersome setup.
5:27 PM
というのはあるけど、notification的なやつって言ってるしこれはベーシックな道具じゃない感じもする
Avatar
omochimetaru 11/1/2020 9:01 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - DougGregor/swift-evolution
9:01 AM
func chop(_ vegetable: Vegetable) async throws -> Vegetable { await try Task.checkCancellation() // automatically throws `CancellationError` // chop chop chop ... // ... guard await !Task.isCancelled() else { print("Canceled mid-way through chopping of \(vegetable)!") throw CancellationError() } // chop some more, chop chop chop ... }
9:01 AM
キャンセルの取り扱いはStructured Concurrencyの方に出てきた。
9:05 AM
func test_cancellation_withCancellationHandler(_ anything: Any) async -> PictureData { let handle = Task.runDetached { () -> PictureData in let file = SomeFile() return await try Task.withCancellationHandler( handler: { file.close() }, operation: { await test_cancellation_guard_isCancelled(file) }) } handle.cancel() }
9:06 AM
コールバック式のやつもPRにあった。
Avatar
The restrictions on only allowing access to (non-async) actor-isolated declarations on self only work so long as we can ensure that the code in which self is valid is executing non-concurrently on the actor.
言いたいことはなんとなくわかるけど、この英文の構造むずくない?
Avatar
今回の Concurrency 関連の Roadmap や Proposal 群の中に Manifesto の Part 3 にあった fault isolation の話ってどこかにありますか? Erlang の actor だと気軽にクラッシュさせられるのが良いみたいですが。まだ読んでない Structured concurrency の方にある? https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782#part-3-reliability-through-fault-isolation
Swift Concurrency Manifesto. GitHub Gist: instantly share code, notes, and snippets.
Avatar
omochimetaru 11/2/2020 2:40 AM
僕は見かけなかったです
Avatar
Phase 3 以降があるのかな・・・
Avatar
omochimetaru 11/2/2020 5:05 AM
今回の方針決定にラトナーはあまり関わってない気がします
5:05 AM
Hi all, I got a chance to write up some thoughts on how to address one of the major challenges with the recent actor model proposal: how do we ensure that values transferred between actors do not introduce shared mutable state. I'd appreciate thoughts and feedback, thanks! ...
5:06 AM
昨日(13時間前)、ラトナーが追加の提案を出したし。
Avatar
Manifesto も Chris Lattner 単独で進めたんじゃなくて Joe Groff も関わってた気がする。
5:18 AM
↓こっちに Joe Groff が入ってるだけで Manifesto は Chris Lattner 単独の名前になってるな。とはいえ、 Core Team で話されてないということはないと思うけど・・・。 https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619
Concrete proposal for async semantics in Swift. GitHub Gist: instantly share code, notes, and snippets.
Avatar
omochimetaru 11/2/2020 8:16 AM
ラトナーが4つのスレ全部で凄いたくさん感想とか質問とか投稿してるんですよね
8:17 AM
まーコアチームでも話してた事をもっかい公の場で投稿してるのかもしれんけど
Avatar
今回のに Chris Lattner が噛んでたかは別として、前回のマニフェストを Core Team で議論してないわけはないと思うから、 Fault Isolation についても Core Team は検討したと思うんよね。
Avatar
omochimetaru 11/2/2020 8:28 AM
それはそうですね。
Avatar
It’s not just the brand new CPUs that will improve your compile times. This PR by @hollyborla and @gregtitus optimizes operator type checking performance as well: https://t.co/TwtRN7Au1h
7:13 PM
演算子たくさん使った式が推論できない問題がだいぶ改善したっぽい
🙌 3
7:14 PM
7:14 PM
式に現れるオペランドが全部同じ型であるケースを先に探索するというヒューリスティックスっぽい。
Avatar
おっ!
7:30 PM
試したい
Avatar
オペランドの型が全部同じと仮定ということは、 isFoo || a + b + c + d + e + f + g >= 0 みたいなのはダメか。
Avatar
実装読んでないのでなんとも言えないですがprecedanceごとに区切って探索とかはあってもよさそう
12:03 AM
木構造は型決定以前に決まるはずなので
Avatar
アプリカティブスタイルがちゃんと使えるようになる?
Avatar
@t.ae たしかに、全部が同じという仮定と全探索の中間に、precedenceグループごとが同じ型になっている、という仮定も置けるね。 その場合は結局複数のグループごとの組み合わせ探索は起きうるけど。
Avatar
そのPRこのスレッドでも話題に出てましたね https://forums.swift.org/t/boolean-comparison-causes-extremely-slow-compilation/41609
Since we moved parts of our codebase to swift, our compile times have effectively quadrupled. Trying to combat this, we've used the function and expression debug time flags to figure out if there's something to be saved by simplifying expressions. Apart from the usual suspect...
Avatar
@swift-5.3.3 @swift-main import Glibc let createMode = Int(S_IREAD | S_IWRITE | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
Avatar
execution timeout with no output
Avatar
swiftNightly BOT 11/11/2020 8:22 AM
execution timeout with no output
Avatar
@swift-5.3.3 import Foundation func measure(_ body: () -> Void) { let start = Date.timeIntervalSinceReferenceDate for _ in 0 ..< 10 { body() } let end = Date.timeIntervalSinceReferenceDate print((end - start) / 10) } let n = 1000 func makeNestedArray() -> [[Int]] { var a: [[Int]] = [] for _ in 0 ..< n { a.append((0 ..< n).map { _ in Bool.random() ? 1 : 0}) } return a } do { var a = makeNestedArray() measure { let y = (0 ..< n).randomElement()! for x in 1 ..< n { a[y][x] &+= a[y][x - 1] } } } do { var a = makeNestedArray() measure { let y = (0 ..< n).randomElement()! for x in 1 ..< n { let t = a[y][x - 1] a[y][x] &+= t } } } (edited)
Avatar
0.0003666043281555176 5.6803226470947266e-05 (edited)
Avatar
↑これおかしくないですか? a[y][x] &+= a[y][x - 1]let t = a[y][x - 1] a[y][x] &+= t に変えると速くなるんですけど、おそらく前者は CoW のコピーが走ってると思います。
10:40 AM
でも、 a[y][x] &+= a[y][x - 1] でも右辺は &+= の実行前に評価が終わっているから、リファレンスカウントに関係なくて良いはず。
10:41 AM
昨日の AtCoder Beginner Contest 183 の E 問題で、おそらく↑が原因で、 Swift だと TLE (制限時間オーバー)になるという声を 2 件聞きました。
Avatar
SILを確認してみたんですが確かにa[y]のリリースの位置が違いました
11:36 AM
前者はループの最後、後者はtをgetした直後にリリースされてました。それ以外は全く一致してます
Avatar
なるほど。前者でもリリースのタイミングを &+= をコールする直前にできますよね?
Avatar
できますね。SILレベルで命令を入れ替えてmodifyする前にリリースするようにしたところ前者と同じくらいのパフォーマンスになりました
🙂 1
Avatar
SILレベルで命令を入れ替えて
これはコンパイラを修正したわけではなく、出力された SIL を直接修正したということですか?
Avatar
そうですそうです。emit-silしたやつを書き換えました。
Avatar
僕にできるかわからないけど、コンパイラの PR にチャレンジしてみようかな・・・。
💪 1
Avatar
このぐらいなら最適化でホイスティングされると思ってたんですけど、-Oでも同じ結果なんですね (edited)
Avatar
そうなんです。 < -O
Avatar
@swift-main import Foundation func measure(_ body: () -> Void) { let start = Date.timeIntervalSinceReferenceDate for _ in 0 ..< 10 { body() } let end = Date.timeIntervalSinceReferenceDate print((end - start) / 10) } let n = 1000 func makeNestedArray() -> [[Int]] { var a: [[Int]] = [] for _ in 0 ..< n { a.append((0 ..< n).map { _ in Bool.random() ? 1 : 0}) } return a } do { var a = makeNestedArray() measure { let y = (0 ..< n).randomElement()! for x in 1 ..< n { a[y][x] &+= a[y][x - 1] } } } do { var a = makeNestedArray() measure { let y = (0 ..< n).randomElement()! for x in 1 ..< n { let t = a[y][x - 1] a[y][x] &+= t } } }
Avatar
swiftNightly BOT 11/16/2020 4:26 PM
0.0021299004554748537 8.890628814697265e-05
Avatar
これはアカン奴や
Avatar
Hello all, We posted the first drafts of a number of proposals related to Swift concurrency a few weeks ago. At this time of this writing, the forum topics directly related to the concurrency proposals have more than 600 posts in total (!), which includes lots of great ideas for design improvements, requests for clarification, and so on. We'll ...
4:32 AM
非同期関係の方針の更新
4:34 AM
プロポーザルを4つから7つに分離する、reasync、アクターの同期メソッドを外から非同期で呼べる
Avatar
reasync 👀
Avatar
Taskライブラリはちゃんと知りたかったし分離されて助かる
4:37 AM
非同期コンテキストの新規作成はTask.runDetachedだよって7でコンラッドが書いてる、やはりそうなんや
Avatar
reasyncやっぱ最初の4本で言及なかったんだね
Avatar
Kishikawa Katsumi 11/21/2020 10:38 AM
AppleシリコンでFloat80使えないのかな? error: 'Float80' is unavailable: Float80 is not available on target platform.
Avatar
x86系だけでは?
Avatar
Kishikawa Katsumi 11/21/2020 11:46 AM
そうみたいですね
Avatar
Kishikawa Katsumi 11/21/2020 2:33 PM
そもそもの、__float80がx86独自タイプなんすね。 (edited)
7:16 PM
TLDR; まぢlibdispatch害悪だわー、asyncなんていらんかったんや。SwiftのActorもおんなじ間違いするんでねーの?
Avatar
人類にマルチスレッドは早すぎたという点(←そうは書かれてないが)には同意しておきます 😌
Avatar
早すぎたんだ... (わかる) (edited)
Avatar
それはともかく、意味がわかっている人の手間やミスを防ぐために簡単にしたツールを提供すると、意味がわかってない人も簡単に使えて悲劇が起こるというのは、libdispatchだろうがActorだろうがどうしようもない気がしますね。と、DispatchQueueを雰囲気で使ってるぼくがいう。
Avatar
いや、でもそれはその通り、この主張のなかで問題だと思っている部分
11:28 PM
libdispatchは被害者とも言える
11:30 PM
でもasyncにしだしたら、全部asyncになって逆にパフォーマンス落ちたとかわかりみがすごい
Avatar
悲劇としか言いようが・・・ 😭
11:33 PM
libdispatchも被害者だが、この記事の人も被害者で、Actorが出るとまた被害者が増えるのもたぶん予見通り。
Avatar
もしかして、微細化できなかったIntelが悪いのでは?
Avatar
ひどいw
Avatar
非同期処理が明らかに向いてる(NWやIO)みたいなのは手動でasyncとか使えると良くって
1:03 AM
それ以外はコンパイラがなんとかしてくれる世界が嬉しいなぁ
Avatar
omochimetaru 12/1/2020 4:15 AM
途中まで読んだけど、使いすぎてオーバーヘッドが増えたりデバッグしづらくなった、って、そりゃあそう
4:16 AM
意味がわかっている人の手間やミスを防ぐために簡単にしたツールを提供すると、意味がわかってない人も簡単に使えて悲劇が起こる
完全にこれでしょう
Avatar
極論プログラミング言語は悪でわかってるやつが機械語書く世界が良いになってしまうから、なんともや
Avatar
omochimetaru 12/1/2020 4:17 AM
「マルチスレッドが速いんでしょう?じゃあ全部マルチスレッドにしろ!」ってやって自爆する話はiOSやDispatchQueueに限らず昔から聞きますね
Avatar
CS多少齧ってればマルチスレッドのオーバーヘッドがどの程度あってとかは履修するから
4:18 AM
前提知識の欠如というか
Avatar
omochimetaru 12/1/2020 4:19 AM
というか小規模なところで計測したらわかるよね。
Avatar
asyncに関していうと、functionにasyncのアノテーション付けるだけでは真に非同期になるわけではないので
Avatar
omochimetaru 12/1/2020 4:19 AM
「書き換えまくってたらいつのまにかアプリの性能が落ちてた」というスタンスはそもそもDispatchQueueに限らずいろいろやらかしそう
Avatar
わからない太郎がパフォーマンスに著しい破滅をもたらすかというと、そうはならない気はしている
4:20 AM
「せやclassからstructに書き換えたろwww」「メモリ枯渇したンゴ、structは悪!」 とか容易に想像できますね (edited)
Avatar
omochimetaru 12/1/2020 4:22 AM
確かに実際のawaitポイントが無いasyncならスレッドコンテキストはそのままなのでそこまで遅くはならないけど、呼び出し側でコルーチンへの書き換えは起きるから、少しは非効率なコードになるはず
Avatar
本人が気付かなければ幸せなままなので
4:23 AM
そういう意味でも被害は小さい
Avatar
omochimetaru 12/1/2020 4:23 AM
4:23 AM
多分
4:23 AM
なんでもActorにする、は、
4:23 AM
制限が強くなるので早々に諦めるので大丈夫なんじゃないかな
Avatar
norio_nomura 12/2/2020 1:48 AM
Concurrency ついていける気がしない… https://twitter.com/Catfish_Man/status/1333936848150745089
This is cute. Dependency diagram showing which in-flight Swift concurrency proposals depend on which other ones https://t.co/Jq0KxnylOx
Avatar
omochimetaru 12/2/2020 4:13 AM
This PR introduces two new entry points named withUnsafe[Throwing]Continuation() in the _Concurrency module. The two new entry points have the following types: withUnsafeContinuation: &lt;T&...
4:14 AM
withUnsafeContinuation: <T> ((UnsafeContinuation<T>) -> Void) async -> T withUnsafeThrowingContinuation: <T> ((UnsafeThrowingContinuation<T>) -> Void) async throws -> T
4:14 AM
let x: Int = await withUnsafeContinuation { c in c.resume(123) } // x = 123
4:14 AM
beginAsync的なものが出てきた。 (edited)
4:15 AM
UnsafeContinuation という名前なのが面白いですね。
Avatar
一番根底のやつか
Avatar
Kishikawa Katsumi 12/2/2020 4:15 AM
これは今夜読んでみよう。
Avatar
omochimetaru 12/2/2020 4:15 AM
今までのUnsafeはメモリ破壊とかの意味だったけど、非同期制御の基盤が壊れないように、の意味で使ってる
4:16 AM
あと例外の有無で分けてありますね。
Avatar
そうかクロージャの中で同期的にthrowするわけじゃないからrethrowsにできないんですね
Avatar
omochimetaru 12/2/2020 4:19 AM
そうだね
4:20 AM
rethrowといえば
4:20 AM
Hey all, Here's a pitch for a feature that @Philippe_Hausler, @Joe_Groff, @Tony_Parker and I have been thinking about to make rethrows also work for protocol conformances. It's motivated by some of the concurrency work, but is separable and useful on its own. Philippe has been prototyping it in the compiler so we have a fairly good sense that t...
4:21 AM
これが昨日出てた
4:22 AM
プロトコルで受けててもプロトコルのメソッドがrethrowsかつ実態の型がnon throwなメソッドでconformしている場合はnon throwになる。
4:22 AM
さっさとtyped throwsに行った方が話が簡単な気がした
Avatar
ややこしくなってきたな
Avatar
omochimetaru 12/2/2020 4:31 AM
Hi everyone, @Philippe_Hausler and I would like to pitch the following proposal. We build on the Swift Concurrency pitches to add the concept of an AsyncSequence to the Swift standard library. An up-to-date version of this proposal can be found here. Async/Await: Sequences Swift's proposed async/await feature provides an intuitive, built-in w...
4:32 AM
for-inのasync版のfor-await-inをする話↑
Avatar
これはべんり
Avatar
omochimetaru 12/2/2020 4:35 AM
asyncな道具が増えてくればこれが欲しくなるときが来るんでしょうね
4:36 AM
まさにサンプルが思いっきり extension URL { struct Lines: AsyncSequence { /* ... */ } func lines() async -> Lines } (edited)
4:36 AM
ってなってるな。
Avatar
べんり
Avatar
for を拡張するなら早く for inout もほしいなぁ。
5:51 AM
↓こういうやつ。 var users: [User] = ... for inout user in users { user.points += 100 }
Avatar
AsyncSequence、Observableみがある
Avatar
omochimetaru 12/2/2020 5:52 AM
for inoutはOwnershipの整理が先ですね、なかなか進まないが
5:52 AM
Observableと似てるね。
Avatar
Observable を operator のパズルで扱うより制御構文で扱えるようになるの良さそう。
Avatar
うーーーん、AsyncSequenceを返す側の構文を考えると
5:53 AM
yield周りの整備をした方が良いような気もするな
Avatar
omochimetaru 12/2/2020 5:54 AM
似てるけど決定的に違うものな気もする
5:54 AM
async(コルーチン)は常に実行箇所が一つなので。
5:54 AM
イベントストリームとそれに対するハンドラを書いてるObservableとは違う。
Avatar
Observableは頼まなくても桃がドンブラコしてくるけどAsyncSequenceは頼まないとやって来ない (edited)
Avatar
omochimetaru 12/2/2020 5:55 AM
発火依頼についてはsubscribeの呼び出しと、for文への到達で対応取れてると思う。
Avatar
正確にはhotとcoldが…
Avatar
hotとcoldはそうすねw
5:56 AM
forとの組み合わせでは対応取れてるか
Avatar
omochimetaru 12/2/2020 5:56 AM
hotでもcoldでも最初につなぐsubscribeの呼び出しとfor文の対応があるのは同じでは
5:57 AM
まあhotなものをasync sequenceで扱うとAPI的な違和感はかなりありそうだけど。
5:57 AM
というかだからそうか、無限ストリームを考えると、
5:57 AM
一箇所のfor awaitに到達したところで実行位置がそこに留められちゃうから
5:58 AM
subscribeを2つ呼ぶようなパターンが扱えないね。
Avatar
zipしたりすんのかね
Avatar
omochimetaru 12/2/2020 5:58 AM
ストリームが分岐してるパターンも無理そう
5:58 AM
マージも無理そうだな、どっちか一つしかawaitできないから、
5:58 AM
流れに合わせて様々な合流戦略を制御するコードが書けない
Avatar
Observableのdo記法相当のはfor文になるだろうなとは思ってたので
5:59 AM
あー
5:59 AM
その辺は解決可能だと思っていて
5:59 AM
Zip2AsyncSequenceやMergeAsyncSequenceを実装して解決する
Avatar
AsyncSequence のための async let 的なものがあるとよい? (edited)
Avatar
AsyncSequenceはfor awaitに対応するprotocolなので、それに対する実装はパターンを持たせレるはず
6:00 AM
実質的にObservableのオペレーターと同じになる
Avatar
zipはいけそうですけど止めるポイントが一箇所しか無いからマージは難しくないですか?
Avatar
イテレータとして扱って任意のタイミングで async letnext を取り出しつつ好きなように合成すれば一応なんでもできそう?多様な operator と同等の処理はそれぞれ関数にするしかなさそうな気が。
Avatar
取り出す手段がfor awaitだけだと、そうですね
6:02 AM
コールバックでも取り出せるようになってれば問題は無くなりそう
Avatar
for await 使わずに next で取り出せますよね?
Avatar
func next() async -> T? になってればokなのは、それはそうですね (edited)
Avatar
omochimetaru 12/2/2020 6:03 AM
ああ、そのnextをFutureに昇格すればなんでもコールバックベースで書けますね。
Avatar
public protocol AsyncIteratorProtocol { associatedtype Element mutating func next() async throws -> Element? mutating func cancel() }
6:04 AM
↑のようです。
Avatar
オペレーター相当のAsyncSequence実装とセットで、現行のObservableのユースケースをかなり食えるイメージ
Avatar
Future に昇格というか、 async let はそれと同じことができるものだと思ってるんだけど違うのかな?まだちゃんと読めてないけど。 (edited)
Avatar
omochimetaru 12/2/2020 6:05 AM
async letは通り抜けておいてawaitした時に止めるものなので
6:05 AM
「3つのうちどれかが到達したら」は結局書けないと思います。
Avatar
↓な理解。どれかが到達はたしかに無理か。 let a = Future { await foo() } let b = Future { await bar() } let c = await a.get() + b.get() async let a = foo() async let b = bar() let c = await a + b
6:11 AM
autoclosure で↓を作るとかかなぁ。 < どれかが到達したら let a = await one(of: await foo(), await bar()) (edited)
Avatar
omochimetaru 12/2/2020 6:12 AM
なるほど。autoclosure awaitってFutureと似たような振る舞いになるのか。
6:12 AM
トリッキーだから普通にFutureで受けたほうが親切な気も。
Avatar
結局autoclosureを使った内部実装でFuture使わざるを得ないと思う
Avatar
omochimetaru 12/2/2020 6:20 AM
あ〜 たしかに。
6:21 AM
autoclosureがasyncな関数だから、内部もまたawait一箇所ルールに縛られるね。
Avatar
そうです
Avatar
omochimetaru 12/2/2020 6:22 AM
てか
6:22 AM
Futureってasync proposalには入ってるんだっけ
6:22 AM
さっきのwithUnsafeContinuationは callback → async だけど、
6:23 AM
Future は async → callback のプリミティブで逆よね
6:25 AM
Hey all, Here's a second pitch of the async/await proposal, which has been revised based on feedback from the first pitch thread. This second document has the following changes from the first pitch: One can no longer directly overload async and non-async functions. Overload resolution support remains, however, with additional justification....
Avatar
ちゃんと読めてないけど、 async/await には入ってなくて、代わりに async let が出てきたのかなと思ってます。
6:27 AM
async → callback の道具が必要なのはそう。
Avatar
omochimetaru 12/2/2020 6:28 AM
structured concurrencyで Task.detached が出てくるんだけどこれは callback → async なんですよね
Avatar
In case you’re up for some light weekend reading, the #SwiftLang async/await proposal is available now and will go into review this coming Tuesday. This is the first of a series of proposals that’s part of the Swift Concurrency effort. https://t.co/upcK0txhOx
11:49 PM
asyncの正規レビュー火曜日 (edited)
Avatar
omochimetaru 12/5/2020 1:02 AM
読んだ 英語読みやすかった 仕様は特に違和感なし
Avatar
実装終わってからレビューなのかあ
Avatar
omochimetaru 12/5/2020 6:59 AM
随分前からそうなりました
Avatar
Kishikawa Katsumi 12/8/2020 7:24 AM
JSの場合async/awaitとmapやforEachって相性悪いけどSwiftの場合はどうなるんでしたっけ? mapのクロージャ内でawaitするみたいなパターン。
Avatar
omochimetaru 12/8/2020 7:25 AM
Swiftの場合、中でawaitできる版をオーバーロードできますね
Avatar
Kishikawa Katsumi 12/8/2020 7:26 AM
async版のクロージャをとる別のmapが追加される?
Avatar
omochimetaru 12/8/2020 7:27 AM
reasyncがあれば自動実装だけど最初のプロポーザルには入ってないのでその別のmapを別途書く
7:28 AM
配列に関してはAsyncSequenceの提案もありますね
7:29 AM
mapだけじゃなくてそもそものリストが非同期に読み込みたい場合があるので。
Avatar
Kishikawa Katsumi 12/8/2020 7:29 AM
どうもどうも。調べてみます。
Avatar
omochimetaru 12/8/2020 7:52 AM
JSでも同じ事ができるはずですけど
7:52 AM
JSだと標準ライブラリに大きな改修は入らないのと、
7:53 AM
overloadが無いから mapAsync みたいな名前が必要になっちゃうことが問題なのかな。
Avatar
Kishikawa Katsumi 12/8/2020 7:54 AM
ああ、確かに。await付きでクロージャを呼び出してくれる版のmapがオーバーロードで利用できるとめっちゃいいですねえ。
Avatar
↓の図には reasync あるんだけど、プロポーザルないんだっけ? https://gist.github.com/DougGregor/444575ac67cbd25bfc4b1d4fd241ae93#file-swiftconcurrencydependencies-svg
Swift Concurrency Proposal Dependencies. GitHub Gist: instantly share code, notes, and snippets.
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
ああ、「最初のプロポーザル」か。後であるんだと思ってたけど、この書き方だとあまり前向きではないのかなぁ。
Avatar
omochimetaru 12/8/2020 8:37 PM
Hi Swift Evolution! The review of SE-0296 — async/await begins now and runs through December 22, 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 (via email or direct message in the S...
8:37 PM
審査はじまた
Avatar
async/awaitもsomeと同じように下位OSでは使えないんですかね🤔
Avatar
そのへんプロポーザルに明記されてないですね ランタイムライブラリがあるので使えない気がしますけど・・・
3:20 AM
I really can't comment on Apple products. The concurrency runtime support library is built as a separate library 3 that builds upon existing APIs (e.g, libdispatch) that have been around for a while. If you grab the right PR 4 and use a hack to start async code, it works fine on generally any macOS.
3:21 AM
25でマックスが質問して31でドーグが答えてる
3:24 AM
今まで言語機能のための組み込みのライブラリはstdlibしかなかったから、
3:24 AM
それとは別扱いの可能性もあるのかも
Avatar
是非使えるようになってほしいですね。。
4:59 AM
浸透するまで2~3年待つのは辛い😂
Avatar
タイミング的に
5:05 AM
WWDC2021でSwift6、asyncawait, iOSですぐ使えます!
5:06 AM
みたいになるかな?
💯 1
Avatar
libswiftConcurrencyが静的リンクでバックデプロイできればワンチャン…
Avatar
Apple「なんで最新のiOS使わないの?」
5:50 AM
本気でそれがAppleの答えだから困る
😅 1
Avatar
Hi Swift Evolution! The review of Concurrency Interoperability with Objective-C begins now and runs through December 22, 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 (via direct me...
9:05 AM
非同期審査第2段はobjc連携
9:06 AM
ここで、asyncとクロージャの相互変換が発生するが
9:06 AM
その際の生成コードについても言及されてる
9:07 AM
それによると、 クロージャ→asyncはwithUnsafeContinuation
9:07 AM
async→クロージャはTask.runDetached
9:07 AM
となるようです。
Avatar
https://twitter.com/dgregor79/status/1337643590386733057 Structured concurrency 使ったマージソート実装。パフォーマンスはわからないけど、なるほどねーっと。
For a little Friday evening fun, I borrowed the merge sort implementation from @rwenderlich ‘s Swift Algorithm Club, sprinkled in a little async/async let/await, and lo! It ran as a parallel merge sort. https://t.co/2lpm3NqER3
Avatar
async let使いやすそうですね
9:23 AM
この例は、部分配列をコピーしてるので、遅そうだけど。
Avatar
その実装、swiftNightlyボットで実行可能になりました。
👀 1
Avatar
Kishikawa Katsumi 12/13/2020 12:28 PM
https://swiftfiddle.com/5nche4blg5b7bkvcvw3mribpbq SwiftFiddleでも使えるようになりました。
SwiftFiddle is an online playground for creating, sharing and embedding Swift fiddles (little Swift programs that run directly in your browser).
👀 1
Avatar
Kishikawa Katsumi 12/13/2020 3:31 PM
Nightly BuildのDockerイメージ、masterがmainに変わったからタグ名も変わったんだけどmasterをmainにマップしたらいいと思うんだけどmasterが止まってmainが別にできたんだよな。別にどっちでもいいんだけど。
3:31 PM
ちょっと不思議に思ったという話。
Avatar
Kishikawa Katsumi 12/13/2020 3:55 PM
SwiftFiddle is an online playground for creating, sharing and embedding Swift fiddles (little Swift programs that run directly in your browser).
3:55 PM
出るなあ。なんで上は出なかったのかしら。 (edited)
Avatar
func mergeSort<T: Comparable>(_ array: [T]) async -> [T] { func f(_ array: ArraySlice<T>) async -> [T] { guard array.count > 1 else { return Array(array) } let middleIndex = array.startIndex + array.count / 2 async let leftArray = await f(array[array.startIndex..<middleIndex]) async let rightArray = await f(array[middleIndex..<array.endIndex]) return merge(await leftArray, await rightArray) } return await f(array[...]) }
2:27 AM
こうすれば元の配列はコピーされない
Avatar
この例は、部分配列をコピーしてるので、遅そうだけど。
なんでコピーしてるのかわかんないね。 mergeSortRandomAccessCollection を受けて IndexInt とかで縛っておけば良さそうだけど。
Avatar
SwiftのArrayは、読み書きの同時アクセスに対して、たとえインデックスが異なっていてもスレッドセーフではないです
4:15 AM
その辺でややこしくなるから説明のためにコピーで書いたのかと思います
Avatar
↑の場合同時アクセスは Read しかなくないかな? Write がなければ同時アクセスしても問題ないのでは? (edited)
Avatar
分割して呼びだす部分だけならそうですね
4:26 AM
普通マージソート作る時は、結果の合成もインプレースでやると思います
4:26 AM
なのでまあ元のコードは正確にはCoWが効いてコピーは起きないけど、
4:27 AM
結果の配列の合成のところでアロケーションやコピーがバンバン起きてる
Avatar
そっちはアロケーションしてるけどオーダー変わってないからまあいいんじゃない?と思ったけど、最初に分割する方も無駄だけどオーダーは変わってないか。
Avatar
Kishikawa Katsumi 12/16/2020 5:27 AM
async let 読んだ。 async/await を並べると上から順に1つ1つ待って逐次的な処理になるけど、それを並列に実行するための仕組みなんすね。 (edited)
5:28 AM
上のmergeSortの例だと、普通にawaitで書くとleftが終わってからrightを処理するけどasync letを使って書くとleftとrightが並列に処理されると。
5:29 AM
というのをちょっとした文法の追加だけで自然に簡単に書けるのが良い、ということか。
Avatar
ですね。
5:33 AM
async awaitだけだと逐次的な処理しか書けないけど、async letは並列な処理を書けるようにしてくれる、というまとめ方は良いですね
5:34 AM
ちょっとした機能だと思ってたけど結構良いものに思えてきた
Avatar
Kishikawa Katsumi 12/16/2020 5:34 AM
async letはFuture的なもの(Taskというオブジェクトになるらしい?)を作るように自動的に右辺をWrapするみたいな、感じかな。
Avatar
Kishikawa Katsumi 12/16/2020 5:52 AM
Structured concurrencyは上記のmergeSortの例でいうと、 親のmergeSortの中で定義されたleftとrightのメソッド呼び出し(再帰だから同じメソッドだけど)が子ということで、大元のascync関数から子のasync関数を呼び出すという構造を作れる、ということを言っているのかな?
Avatar
structured concurrencyの他のAPIの機能も見た感じでは
5:53 AM
「子タスクが終わらないと自身が終わらない」という関係があるのが親と子で (edited)
5:53 AM
その親子関係のことがstructuredと呼んでそうと思った
Avatar
例えばTS/JSのpromise+awaitだと、async関数を呼んだ行でブロックする必要がある ので、awaitだと直列にしか書けない これが、async letが入ると任意の行でブロックが可能になり、結果として平行処理の記述が平坦に書けるようになる、という感じで見てます (edited)
Avatar
Kishikawa Katsumi 12/16/2020 5:54 AM
あ、なるほど。でSwiftのasyncはawaitしないということを許さない(合ってる?)から「子タスクが終わらないと自身が終わらない」という関係が作れるということかな?
Avatar
どうなんだろう?async let 宣言した値を await しない場合コンパイルエラーになるんかな?
Avatar
それはならないとおかしいと思うけど
Avatar
なるんだったら完全にそうですね。Future手書きだとawait忘れの可能性がありますもんね。
Avatar
Kishikawa Katsumi 12/16/2020 5:56 AM
プロポーサルにはasync letはScopeに束縛されるからスコープ内でawaitしないとダメ、みたいなことが書いてあったと思う。
Avatar
async let, try に対する try? に似た物を感じる
Avatar
Kishikawa Katsumi 12/16/2020 5:57 AM
JSのasync/awaitだとConcurrentにやりたいときはどうしてもPromise.joinとか出てくるから自然に書けていいですよね。
Avatar
もちろん限界はあって、もっと複雑なことをしようとすると、流石にFuture使うことになるとは思います
5:58 AM
あーでも
5:58 AM
try?もあるから割となんとかなりそうだな
5:58 AM
あと、swiftのasyncはtry-catchと混ざってない(jsは混ざってる)のも
5:58 AM
問題がシンプルになりそうな予感
Avatar
混ざってるってどういう意味?
Avatar
PromiseがFutureとEitherの合成モナドなので
5:59 AM
async/awaitは必然的にtry-catchが発生し得る状態になってる(かつ、もともとtrycatchしなくても怒られないのも相まって中々に
naruhodo 1
Avatar
async throws なのに await try 強制なのちょっと微妙な気が。気持ち的には先に Future<Result<Foo, Error>>Future を先に剥がしたいから try await が正しいと思う。
10:19 AM
ないと思うけど、万が一将来 throwsasyncResultFuture を返すことと交換可能にしようみたいなことが起こった場合に齟齬が出る可能性がある。
10:20 AM
二つだけだと大丈夫か? await だけ使うのは。三つ以上になったときに、一部だけ使うと順番が変になりそう。
Avatar
むむ、たしかに。左右の並びより、内外の対応のほうがきれいな気がする。
4:54 PM
まだレビュー期間だったら書くと良いかも。
Avatar
でもわざわざ順番強制が修正で入ったところにコメントしても覆ることはなさそう・・・。
12:08 AM
まあ意見くらいはしておくか。
Avatar
プロポーザルのリビジョン間で変わってるなら、リビジョンのスレッドで、差分について考慮したこととか書いてあることが多いです
Avatar
iPadOSで、任意の座標をタッチさせる機能は存在しますか?
Avatar
Avatar
dangomushi.3
iPadOSで、任意の座標をタッチさせる機能は存在しますか?
相対的に移動させるのであればマウスでできるんですが、任意の場所へタッチすることが必要であり、マウスデバイスとしてのアクセスはあきらめました。 その代わりにタッチ機能で代替できるのではないかと考えています。
Avatar
Avatar
dangomushi.3
相対的に移動させるのであればマウスでできるんですが、任意の場所へタッチすることが必要であり、マウスデバイスとしてのアクセスはあきらめました。 その代わりにタッチ機能で代替できるのではないかと考えています。
以前同様の内容で質問した時に、Private APIでアクセスすればあるかもしれないという話でしたが、マウスの移動関係のAPIはどこを探せばあるかわかりますか? (edited)
Avatar
#uikit の方が適切かな?
Avatar
Avatar
tarunon
#uikit の方が適切かな?
なるほどです!そちらでも質問します!
Avatar
コメントするまでもなく try await になりそう。
It was suggested that try await reads better than await try. The core team agrees, and the proposal will be modified accordingly.
https://forums.swift.org/t/accepted-with-modification-se-0296-async-await/43318
The review of SE-0296 – async/await has concluded and the proposal is accepted. Feedback was very positive on the concept of adding async/await in general with a few key points raised: It was suggested that try await reads better than await try. The core team agrees, and the proposal will be modified accordingly. There was some discussion of ...
Avatar
acceptedだ
Avatar
Kishikawa Katsumi 1/2/2021 7:14 PM
なんかSwiftのJIRAで報告したIssueがDuplicateで閉じちゃった。
Avatar
さっき大量にadminが閉じてましたね
7:15 PM
ミスか、ほんとにduplicateなのか...
Avatar
Kishikawa Katsumi 1/2/2021 7:16 PM
AppleのRadarに登録したからDuplicateってことなのかな
Avatar
それっぽくもあるし
7:16 PM
単に機械的に古いのは全部閉じたのかもしれないし
7:16 PM
わからない
7:17 PM
このタイミングなのが、新年の仕切り直しっぽくて
7:17 PM
機械的な処理に感じる
Avatar
https://bugs.swift.org/browse/SR-2145?focusedCommentId=60277&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-60277
We are investigating this and other similar incidents, and working to rectify the situation.
(edited)
Avatar
手違いっぽいなあ
7:20 PM
なにがおこったんだろう
7:21 PM
"Changes by Admin on 2 Jan 2021 8:49 AM"
7:21 PM
このadminって攻撃されたのか
7:21 PM
7:21 PM
なるほど
7:22 PM
bad123bb123 さんひどいなあ (edited)
7:25 PM
@johannesweiss @nicklockwood Not a script bug, this was a user (w/ a great nickname bad123bb123 later renamed themselves to Admin, which is the nickname that emails show) that previously tried to upload simple-backdoor.php on different issues, history still available here https://t.co/sgDgfxJUJ7
Avatar
Kishikawa Katsumi 1/2/2021 7:32 PM
なるほど。事故ならしょうがない。
7:32 PM
もうわかってるようで一安心
Avatar
だれかが戻すスクリプト走らせるのかな
7:33 PM
SwiftのJIRAが脆弱だったってことだよなあ...
Avatar
Kishikawa Katsumi 1/2/2021 7:34 PM
最悪1日分巻き戻るとかですかねえ
Avatar
正月開けが週末なのが悔やまれる
7:34 PM
普通なら今日から仕事
Avatar
あれ (edited)
8:19 PM
bad123bb123 が reopen してる...
8:20 PM
ImprovementsとかがBugに変更されてる...
8:20 PM
もうめちゃくちゃだ
Avatar
omochimetaru 1/3/2021 9:52 AM
😭
Avatar
omochimetaru 1/13/2021 2:14 AM
Hello Swift community, The review of SE-0298 "Async/Await: Sequences" " begins now and runs through January 26, 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 revi...
👀 1
2:14 AM
次はAsyncSequenceをやるそうな!
Avatar
omochimetaru 1/15/2021 7:25 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - jckarter/swift-evolution
7:25 AM
Hi everyone. The UnsafeContinuation API, which exposes async task continuations so they can be used to interface with existing synchronous event-based code, were buried somewhat arbitrarily in the Structured Concurrency proposal. Since there are interesting things to discuss about this API particularly, and it's an important part of interfacing ...
7:25 AM
asyncを作るAPIとして
7:26 AM
withUnsafeContinuation が提案されてる
7:26 AM
withCheckedContinuation というのもある。
Avatar
Instead of leading to undefined behavior, CheckedContinuation will instead trap if the program attempts to resume the continuation multiple times.
なるほど
Avatar
omochimetaru 1/15/2021 7:30 AM
これどっち使うか悩ましくない?
Avatar
デバッグするときはCheckedになっててほしいけどリリース時にはオーバーヘッド無いほうが嬉しい。。
wakaru1 1
Avatar
The API is intentionally identical to the Unsafe variants, so that code can switch easily between the checked and unchecked variants.
API 切り替えろってことだと思うんだけど、あんま Swift で見かけない気が。それなら -Ounchecked ならチェックが消えるとかの方が整合性ありそう。
Avatar
言われてそうな気がする スレッド見てみるか
10:16 AM
例外の有無で型を分けずに、エラーの型パラメータをもつようにしてバリアントを減らす意見あるな
10:19 AM
書かれてなさそう
Avatar
rethrowsみたいにできればなぁ
Avatar
例外の有無で型を分けずに、エラーの型パラメータをもつようにしてバリアントを減らす
Never で潰すってこと?複数のエラー型に対応するときは Error で埋めればいいからできるか。将来的に Typed Throws が入る可能性あるならそっちの方がいいかも。
Avatar
3のdanteさんのレスです
Avatar
なるほど。 withUnsafeContinuationwithUnsafeThrowingContinuation は分けたまま UnsafeContinuation に一本化できるってことか。
Avatar
Avatar
omochimetaru
書かれてなさそう
書き込んでみた。
How about switching checked or unchecked automatically depending on if -Ounchecked (or maybe -O) flag is on? It seems consistent with precondition (or assert).
https://forums.swift.org/t/concurrency-continuations-for-interfacing-async-tasks-with-synchronous-code/43619/27
How about switching checked or unchecked automatically depending on if -Ounchecked (or maybe -O) flag is on? It seems consistent with precondition (or assert).
Avatar
お、良いですね!
🙂 1
Avatar
I don't think we can do that automatically because the types are not layout-compatible; CheckedContinuation needs to hold on to a class instance whose lifetime tracks whether the continuation is leaked, whereas UnsafeContinuation can be implemented as a raw pointer to the task structure.
4:52 PM
なるほど?
4:53 PM
なんとかならんもんかな。
Avatar
Kishikawa Katsumi 1/15/2021 4:54 PM
そういうもんなんかな。IFが一緒なんだったらコンパイラフラグを見て実装を入れ替えたらよさそうに思うけど。 (edited)
Avatar
都度ソースからビルドするならいいけど、標準ライブラリとしては難しそうな・・・。 ABI も定まらなさそう。
4:56 PM
でもこれ手で切り替えるのいやですよねぇ😥
Avatar
omochimetaru 1/15/2021 4:56 PM
あ~そういう事かー
Avatar
Kishikawa Katsumi 1/15/2021 4:56 PM
Ouncheckedってビルド済みのものにも影響あるんでしたっけ?
4:56 PM
ああ、違うか。標準ライブラリみたいに添付するものは
Avatar
わかった。自前で作ればいいんだ。
Avatar
Kishikawa Katsumi 1/15/2021 4:56 PM
切り替えられないからってことですね。
4:57 PM
つまり一段ラップしたものを自分で作ればいい、ということっすね。
作ればいい
Avatar
withContinuation を SwiftPM として作って withUnsafeContinuationwithCheckedContinuation を切り替えればいいんだ。
4:58 PM
それだとソースからビルドするからビルド時に切り替えられますね。
Avatar
Kishikawa Katsumi 1/15/2021 4:59 PM
読んでないんですけどwithUnsafeContinuationのメリットはパフォーマンスだけですか?
Avatar
typealias Continuation = CheckedContinuationtypealias Continuation = UnsafeContinuation を切り替えるのも必要か。
Avatar
Avatar
Kishikawa Katsumi
読んでないんですけどwithUnsafeContinuationのメリットはパフォーマンスだけですか?
僕もちゃんと読んでないですけど多分そうだと思います。
Avatar
Kishikawa Katsumi 1/15/2021 5:00 PM
そうだとすると、いわゆる非同期に実行したいものはパフォーマンスが支配的なのは中身だろうから基本的にwithCheckedContinuationを使う、でいいかなという気が私はしていますね。
Avatar
まあここがボトルネックになることもあまりなさそうだし、プロダクションコードが Unsafe だらけになるのも気持ち悪いし、普通に Checked で良さそうな気がしますね。
Avatar
Kishikawa Katsumi 1/15/2021 5:00 PM
はい。そんな手間をかけるメリットあるのかな、という。
5:01 PM
128コアをめっちゃ並列に動かす、みたいなのだと差があったりするのかな?
Avatar
PromiseK でも普通に check してますね。これ使いまくってても特にパフォーマンスの問題感じたことないしなぁ。 precondition だから check 自体は -Ounchecked だと消えるけど。 https://github.com/koher/PromiseK/blob/master/Sources/PromiseK/Promise.swift#L15
Avatar
Kishikawa Katsumi 1/15/2021 5:02 PM
2回呼ばれてないかチェック、はやっぱり排他とったりするから多少コストあるのかな?
Avatar
128コアをめっちゃ並列に動かす、みたいなのだと差があったりするのかな?
こういうのは差があるのかもしれませんが、 CheckedContinuation 使ってても JS で Promise 使ってるより効率良さそうな・・・。
Avatar
Kishikawa Katsumi 1/15/2021 5:06 PM
ちなみにOuncheckedかどうかって取れないっすよね?Ouncheckedと一緒に別のフラグを渡す感じっすか?
5:06 PM
ラッパーを作る場合。
Avatar
ほとんどの部分はネイティブのコルーチンになってるわけで、これ必要なのはつなぎの部分だけの話でしょうし。既存の Obj-C の API が自動で async 化されるときはこれに置き換えられる?
Avatar
Avatar
Kishikawa Katsumi
ちなみにOuncheckedかどうかって取れないっすよね?Ouncheckedと一緒に別のフラグを渡す感じっすか?
うーん、たしかに。 precondition とかどうなってるんでしょう。標準ライブラリだからこそできること?
5:10 PM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
5:10 PM
_isDebugAssertConfiguration とか _isReleaseAssertConfiguration とかで分岐してる・・・。
Avatar
omochimetaru 1/16/2021 2:31 AM
Hi Swift Evolution! The review of SE-0300 — Continuations for interfacing async tasks with synchronous code begins now and runs through January 26, 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 re...
2:31 AM
継続API、正式審査開始
Avatar
Swiftで継承とプロトコルとprotocol extensionが絡んだ時に呼び出されるメソッドがわかりづらい事があるのでまとめました。 バージョン $ swift --version Apple Swift version ...
4:35 AM
vtable/witnesstableのあれで爆死したコードを今日引いて多数のチームの人の数時間を溶かしたので気を付けたい
Avatar
これ何回やっても壊れがちで辛い
4:55 AM
全部ちゃんとテーブルに乗る実装にするのが吉
Avatar
辛い
Avatar
これ パターン B が直感的に見落とすよなぁ… (edited)
Avatar
runAsyncAndBlockから @main struct Main { static func main() async { await runTest(numCounters: 10, numWorkers: 100, numIterations: 1000) } } になった https://github.com/apple/swift/pull/35642
2:39 PM
@main struct Main func main で3回もmainが出てくる
😭 2
Avatar
@main func main(){} でいいのでは、、、、、
Avatar
async/awaitの練習問題作り直さないと早速動かなくなりそう😭
Avatar
Kishikawa Katsumi 1/29/2021 4:05 PM
Main.mainの名前はなんでもいいんですよね?
Avatar
omochimetaru 2/3/2021 7:23 AM
Hi all, Here's a pitch for a feature that expands #if functionality to postfix member expressions. I'll keep an update-version of this proposal here. Implementation is here #if for postfix member expressions Swift has conditional compilation block #if ... #endif which allows code to be conditionally compiled depending on the value of one or m...
7:24 AM
りんたろーさんがピッチ出してて、 メソッドチェーンを #if できるようにする話 baseExpr #if CONDITION .someOptionalMember? .someMethod() #else .otherMember #endif
7:25 AM
おしゃれと思ったら、 >>2 でラトナーが、Swiftの #if の路線間違いだったと思うって書いててビックリ
7:25 AM
そのあとakyさんと意見交換してて面白い。
Avatar
FWIW I disagree; the approach of the parser being able to understand all of the code, independent of #if sections and compiler arguments (truly context-free), is what allowed us to support syntactic understanding of the code everywhere (syntax coloring, indentation, formatting, structure view, etc.) with just a source file or text as input.
なるほどたしかに
Avatar
omochimetaru 2/3/2021 9:00 AM
有効じゃない方のコードの健全性がチェックできるのが良いところだよね
Avatar
@swift-main -Xfrontend -enable-experimental-concurrency import Foundation func foo() async {} @asyncHandler func bar() { print("bar A", Thread.current) await foo() print("bar B", Thread.current) } print("main A", Thread.current) bar() print("main B", Thread.current) (edited)
Avatar
swiftNightly BOT 2/9/2021 2:06 AM
main A <Thread: 0x000000000ac0fa70> main B <Thread: 0x000000000ac0fa70> (edited)
Avatar
@asyncHandler の中(の最初の suspension point まで)は同期的に実行されない??
2:10 AM
@asyncHandler の中のスレッドが呼び出し元と変わっているという報告を受けました。
Avatar
omochimetaru 2/9/2021 2:10 AM
そうみたいですね
2:10 AM
実際
2:10 AM
async contextが変わらないようにするためには
2:10 AM
そうするしかないような気がする
2:11 AM
barの開始した場所と、barの再開後は同じコンテキストじゃないといけないけど
2:12 AM
barの呼び出しから最初の停止までが同期的だと、同期的な推移は同じコンテキストになるはずだから (edited)
2:12 AM
コンテキストが二つに増殖しちゃって一貫性が欠けそう
Avatar
その async context ≒ Task
Avatar
omochimetaru 2/9/2021 2:14 AM
Task.currentだったかな?
Avatar
async 関数を抜けるまでは Task を専有してないといけないけど、 @asyncHandler が付与された関数が同期的に実行されるなら bar の呼び出し元と bar の中は同じ Task に属していなければならない。そうすると bar の中の await (suspension point) で bar を抜けたときに呼び出し元の bar の後続処理が、 bar が専有しているはずの Task で行われてしまっておかしい、と。
2:20 AM
同期的な場合にスレッドはそのまま Task だけ切り替えることは絶対できないんだっけ?できなさそうな気がするけど確信が持てない。
Avatar
omochimetaru 2/9/2021 2:43 AM
絶対できない
絶対できないということはないかも・・・?コンパイラが呼び出し前に切り替え処理を挿入すればいいから。
2:44 AM
でも、今の所そういう挙動は存在してないから、
2:44 AM
asyncHandler の場合だけそういうことが起きるようになるのは良くないと思う。
2:45 AM
他の、同期からTaskを開始するAPIとしては Task.runDetached があるから
2:45 AM
asyncHandlerの呼び出しと、自分でTask.runDetachedで呼び出しをラップするのが
2:45 AM
同じ挙動になっているという仕様にしたいんじゃなかったっけ
2:50 AM
asyncHandlerの挙動設計について議論されてる文書がどこにあるか忘れた・・・
Avatar
asyncHandlerはまだProposalのDraftもなかった気がする。Forumに分散してコメントがあったような気も? @asyncHandler は別スレッドで非同期、同期的処理は Task.runDetached (を呼ぶ前に)ということになりそうだね。 (edited)
Avatar
Hi all, Thank you for all the great feedback on the proposal. Doug and I have been iterating on it a bit and have a draft #4 up. My sense is that this is getting close to convergence for a formal review. This proposal differs from draft #3 in the following major ways: This includes a more explicit definition of marker protocols. Conformanc...
11:19 AM
ConcurrentValue のピッチを読んだけどなかなかおもしろいです。
11:19 AM
SwiftにActorが導入されてアクターアイソレーションが導入されたとしても、
11:21 AM
参照型のオブジェクトをアクター間で受け渡してしまったら、 共有オブジェクトに並行同時アクセスすることになるので、スレッドバグが起きてしまうわけです
11:21 AM
そこでこのピッチで解決しようとしているのが
11:21 AM
「スレッドをまたいで受け渡しても安全である型かどうか」を静的に検査する仕組みを作ろうということです
11:22 AM
Swiftには値型があるけど、値型のプロパティとして参照型を持っていたらだめだとか、 参照型だったとしても、immutable class patternだったら安全であるとか
11:22 AM
そのへんをマーキング用のプロトコル ConcurrentValue で示す+コンパイラがデータ構造をチェックする
11:23 AM
によって保証しようとのこと
11:23 AM
UnsafeConcurrentValueというのもあって、これは、 検査なしで強制的にConcurrentValueにするためのマーカー。
11:23 AM
それと、関数型に対する @escaping のように @concurrent という属性も追加して
11:24 AM
関数がマルチスレッドセーフかどうかも検査します
11:24 AM
例えば何もキャプチャしていないクロージャなら、2つのスレッドから同時に使っても大丈夫だけど
11:25 AM
var をキャプチャしていると、そこを介してミュータブルステート共有が起きるのでだめだとか
11:25 AM
そのあたりをチェックするそうです
Avatar
RustのSend/Syncっぽい
Avatar
Rustにもなんかあるよね よく覚えてないけど 結構違うものな気がする
11:27 AM
Swiftは言語自体に参照型の概念とアクターが入ってて、それを踏まえてこの機能が設計されてるから、使いやすそう (edited)
11:27 AM
Rustは、結局unsafeだらけになってしまうという話を聞いた事がある
Avatar
コンパイラが自動でtrait実装を提供できないとunsafeがでてくる…
Avatar
ふむ
11:33 AM
jroseさん
It’s weird to read this whole part of the proposal without any reference to Rust’s Send and Sync, which work very similarly. I don’t think we’re going to need both protocols in Swift, but it’s absolutely prior art.
Avatar
これはモジュール外の型を後からConcurrentValueに準拠させたいときどうなるんだろう
Avatar
Avatar
omochimetaru
jroseさん
It’s weird to read this whole part of the proposal without any reference to Rust’s Send and Sync, which work very similarly. I don’t think we’re going to need both protocols in Swift, but it’s absolutely prior art.
なるほど
Avatar
Equatableとかと同じでextensionで後付けできるって話だったような いや、わからん、見直したけど言及が見つからず。 (edited)
Avatar
Equatableのあと付けって基本同一ファイルでしかできなかった気がするんですよね
Avatar
なるほど。
Avatar
外からだとprivateなフィールドが見えなくなっちゃうので
Avatar
これに関してはマークだけで実装が無いからその点は平気そう
11:38 AM
ちなみにクラスに関しては
11:38 AM
たとえプロパティとして値型のletしか持っていなかったとしても (edited)
11:38 AM
継承して追加したフィールドにmutable stateが生えるかもしれんから駄目
11:39 AM
たとえfinal classだったとしても、
11:39 AM
ABI互換を保った新しい実装がmutable stateを増やしているかもしれんから駄目
11:39 AM
final かつ frozen なら許せる気がするがややこしいのでこのピッチでは先送り
11:39 AM
って書いてあった。
11:40 AM
よってクラスの場合は UnsafeConcurrentValue をエイヤでつけることしかできない。
Avatar
Avatar
omochimetaru
これに関してはマークだけで実装が無いからその点は平気そう
ユーザーに見える実装がなかったとしてもコンパイラが何らかのコード生成をする気がするんですよねー。
11:41 AM
ピッチちゃんと読んでみます
Avatar
いや、それは、ないって明言されていて
11:42 AM
らとなー
One of the interesting-to-me realizations is that these marker protocols are vaguely attribute-like (since they are compile time only). The problem with this viewpoint is that we want ConcurrentValue to participate in the generics system, and making attributes do that would open a ton of complexity we don't want.
11:42 AM
マーカープロトコルはアトリビュート的(コンパイルタイムだけだから)
11:43 AM
と >>5 でも書いてるしピッチにもなんかそれっぽい話があった
11:44 AM
This proposal introduces the concept of a “marker” protocol, which indicates that the protocol has some semantic property but is entirely a compile-time notion that does not have any impact at runtime.
11:44 AM
これだ。 ConcurrentValue個別の話にはいる前に 「Marker Protocols」について定義?している。
Avatar
omochimetaru 2/12/2021 2:35 AM
Custom Executor Pitch と Structured Concurrency Pitch を読み直してるけど、だんだんわかってきた
2:38 AM
async関数がsuspension pointによって区切られた個別の同期処理にPartial Taskとして分解されていて
2:39 AM
これはUnownedJobRefとしてopaqueに表現されて
2:39 AM
Executorはenqueueメソッドでそれを受け取る。 Executorが実行するときにはjob.executeを呼ぶ。 ここがダブルディスパッチなのは、Executorがスケジューリングやスレッドホッピングなどをするため。
2:41 AM
という理解であってるんかな。 SerialExecutorのgiveUpThreadとかはまだよくわかっていないけど
2:42 AM
ActorがExecutorにタスクを投入する前に
2:43 AM
tryClaimThreadして成功したら直接実行してgiveUpThreadで戻す てことなんかなあ。
2:43 AM
スレの会話によるとDispatchQueueがasyncメソッドでもスレッドスイッチしないでmutexですませるキューカウント0のときの話と似た話をしていた
2:46 AM
なんでTaskGroup.add自体がasyncなんだ。
Avatar
Custom Executorが入るとJSイベントループ向けのExecutor実装が綺麗になって嬉しいな
Avatar
omochimetaru 2/12/2021 4:23 AM
たしかに。
Avatar
今はヘッダをコピーして、テスト用に開けられたフックポイントを使って実装してる https://github.com/swiftwasm/JavaScriptKit/pull/112/files
Avatar
omochimetaru 2/12/2021 4:25 AM
なんかめっちゃいろいろinclude追加してるな
4:26 AM
Executor.hがほしかったけどそこから芋づる式になってしまったやつか
👈 1
4:27 AM
global executorを実行時に差し替える仕組みも用意するってPitchに書いてあるし
4:27 AM
きれいになりそう
Avatar
まさに求めてたやつ
4:28 AM
あとはSwiftNIOが嬉しいのかな
Avatar
omochimetaru 2/12/2021 4:31 AM
どうなんだろう・・・ channelReadとchannelRead0とか
4:32 AM
channel周りの設計ってうまくactorに乗るのかな
Avatar
Hey there, realistically all this will take quite some time to pan out and fully understand all the implications on APIs. However a few "simple" things that can be done early are: The concurrency design offers Task.Handle APIs which effectively are "futures" but married together with the async world. When you look at it you realize it's not v...
Avatar
omochimetaru 2/12/2021 4:32 AM
よくわかっていない
Avatar
It is not entirely clear how NIO would be expressed as actors
Avatar
omochimetaru 2/12/2021 4:33 AM
コンラッド先生がそういってるんかw
4:33 AM
でも8月の書き込みだし進捗してそう
4:33 AM
Handlers are pretty similar to actors in that they isolate state and run not concurrently
(edited)
4:33 AM
NIO will want to "don't hop to other executor because that executor is the same event loop as my event loop"
4:33 AM
なるほど。
4:34 AM
ktoso Konrad `ktoso` Malawski 🐟 8d Good morning everyone :wave: To follow up here, the concurrency efforts now gained another proposal: Custom Executors 19 which relates to some of the questions posed in the thread. As in: an EventLoop could be a custom executor.
4:34 AM
てか最新の書き込みで、EventLoopがCustom Executorになるだろうとさ (edited)
Avatar
はやくasync/awaitでServer Side Swift書きたい
👀 1
Avatar
omochimetaru 2/12/2021 4:37 AM
めっちゃ楽になりそうなんだよな〜
Avatar
omochimetaru 2/12/2021 7:21 AM
static func withCancellationHandler<T>( handler: @concurrent () -> Void, operation: () async throws -> T ) async rethrows -> T
7:22 AM
同期的割り込みキャンセルのインターフェース例も追記されてた
7:22 AM
これがちゃんとあるのかがずっと心配じゃった
Avatar
omochimetaru 2/15/2021 8:11 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
8:11 AM
継続APIの3回目のレビューで、Throwingな型が廃止されて
8:12 AM
型パラメータとしてエラーの型を取るようになった
Avatar
NonThrowならEにNeverを入れるってことね
Avatar
omochimetaru 2/15/2021 8:14 AM
func withUnsafeContinuation<T>( operation: (UnsafeContinuation<T, Never>) -> () ) async -> T func withUnsafeThrowingContinuation<T>( operation: (UnsafeContinuation<T, Error>) throws -> () ) async throws -> T
8:15 AM
ですね。withのやつはそのまま
8:18 AM
NeverかErrorのどっちかしか埋まらないのかな?自分で作る方法がないもんな
Avatar
これはうーん
8:25 AM
まあそうなるか
Avatar
結果がResult<T, E>で取れるAPIが生えても良さそう
Avatar
Result<T, E>と入れ子にするのとどっちがいいんだろう、って思った
Avatar
Avatar
Yuta Saito
結果がResult<T, E>で取れるAPIが生えても良さそう
omochimetaru 2/15/2021 8:26 AM
いまresumeしかないからasyncでやる事しかできないね
Avatar
UnsafeContinuation<T>にして func withUnsafeContinuation<T>( operation: (UnsafeContinuation<T, Never>) -> () ) async -> T func withUnsafeThrowingContinuation<T, E: Error>( operation: (UnsafeContinuation<Result<T, E>>) throws -> () ) async throws -> T にすれば、throwsで受けることもResultで受けることもできそうだ
8:33 AM
でもContinuationだから継続の話ですよね、だとするとError発生は中断させたいはずで、Result入れ子は不適切だと思う
Avatar
そうかーなるほど
Avatar
omochimetaru 2/16/2021 1:37 AM
Hello again, everyone, After yet more interesting discussion in pitch #2, we've revised the actor proposal for this, pitch #3. Changes in the third pitch: Narrow the proposal down to only support re-entrant actors. Capture several potential non-reentrant designs in the Alternatives Considered as possible future extensions. Replaced @actorInd...
1:38 AM
アクターがピッチ3になってだいぶ読みやすくわかりやすくなった
Avatar
Avatar
Yuta Saito
結果がResult<T, E>で取れるAPIが生えても良さそう
これよくわからなかったんですが、 func resume(with result: Result<T, E>) のことではなくて、 withUnsafeThrowingContinuation の戻り値を Result で受け取りたいケースってことですか?
Avatar
そうですね。こういうのを考えてました func withUnsafeThrowingContinuation<T, E>( operation: (UnsafeContinuation<T, E>) -> () ) async -> Result<T, E> (edited)
Avatar
withUnsafeContinuationThrowing でない)を T == Result<U, Error> に対して呼び出して resume(returning:)Result<U, Error> を渡すのはダメですか?
Avatar
おそらくそれと等価だと思います
4:06 AM
ただせっかくUnsafeContinuationにパラメータEが付いてるのに勿体ないな…と
Avatar
withUnsafeThrowingContinuation だと Error になっちゃうけど、 withUnsafeContinuationresumeResult を渡す場合はエラーの型を温存できるんじゃないでしょうか。
4:11 AM
let result: Result<Foo, FooError> = await withUnsafeContinuation { continuation in barAsync { result in continuation.resume(returning: result) } } (edited)
4:12 AM
ああ、 UnsafeContinuationE は有効活用できてないですね・・・。
Avatar
UnsafeContinuation<Result<T, E>, Never> だとUnsafeContinuation自体のエラー型がNeverで埋められてしまうのが
4:12 AM
そうですそうです (edited)
4:13 AM
実用上は問題ないと思いますw
Avatar
typed throws が導入されれば変わるのかもですが、このあたりも含めて変えるの大変そうですね。
Avatar
omochimetaru 2/20/2021 4:35 AM
Hello, Swift community. The review of SE-0302: ConcurrentValue and @concurrent closures begins now and runs through March 1st, 2021. This review is part of the large concurrency feature, which we are trying to review in many small portions. While we've tried to make it independent of other concurrency proposals that have not yet been reviewed...
👀 1
4:35 AM
レビュー
Avatar
Kishikawa Katsumi 2/23/2021 7:58 AM
https://swiftfiddle.com/gozs3j2nabfsdehsb56tl2roje Async/Await、Linuxでも期待通りに動くようになった気がするんだけど誰か合ってるか見てくれません?
SwiftFiddle is an online playground for creating, sharing and embedding Swift fiddles (little Swift programs that run directly in your browser).
👀 2
8:00 AM
このコードがAwaitしてる見た目で単にブロックしているとかではなくて、ちゃんと別スレッドで動いているのをAwaitで待っているという本来のAsync/Awaitの動きを示すコードと動きになっているかどうか。
Avatar
このPR以降はLinuxでもlibdispatchの上で動くようになったので、ちゃんと別スレッドで動いてるはず…! https://github.com/apple/swift/pull/35871
Avatar
Kishikawa Katsumi 2/23/2021 8:15 AM
おおー、つい最近だ。いいですねえ。
Avatar
あと最新の書き方だとエントリポイントはこうなります @main struct Entrypoint { static func main() async { print("task started") do { let data = try await download("https://httpbin.org/get") let response = try await parseJson(data) print(response) } catch { print(error) } print("task end") } }
Avatar
Kishikawa Katsumi 2/23/2021 8:16 AM
main() async でいいのか。やってみよう。 runAsyncAndBlock使わなくていいってことですよね?
Avatar
Fiddleで試してみたんですけど、トップレベルのコードが別にあるっぽい? /[REDACTED]/main.swift:48:1: error: 'main' attribute cannot be used in a module that contains top-level code @main ^ /[REDACTED]/main.swift:1:1: note: top-level code defined in this source file import Glibc ^
8:16 AM
そうですー
Avatar
Kishikawa Katsumi 2/23/2021 8:16 AM
そうそう。mainに包んで実行している。
Avatar
なるほど
Avatar
Kishikawa Katsumi 2/23/2021 8:17 AM
そうしないと毎回自分でmain書かないと動かないから。 async mainのコードに包むようにしてみる。
🤩 1
8:22 AM
違った。swiftcじゃなくてswiftで実行してるからいくつか足してるコードがあるのはそうなんだけど、main()は別に作ってなかった。
8:23 AM
swiftでスクリプト的に実行するコードだとトップレベルでawaitするのは無理かな?
Avatar
そうなのかな…?
8:24 AM
手元で試してみよ
Avatar
Kishikawa Katsumi 2/23/2021 8:27 AM
今までのコードを @main struct Entrypoint { static func main() async { // <= ここに入力コード } } のようにして $ swiftc -parse-as-library ./main.swift $ ./main
8:27 AM
だと動きそう。
Avatar
ふむふむ
8:28 AM
-parse-as-library はなに用ですか?
Avatar
Kishikawa Katsumi 2/23/2021 8:30 AM
こうしないと@mainがついたコードをコンパイルしてくれなkった。
Avatar
おぉ
8:33 AM
ホントだ @mainに書き換えるタイミングで-parse-as-libraryも付くようになってる https://github.com/apple/swift/pull/35642/files
Avatar
Kishikawa Katsumi 2/23/2021 9:06 AM
main() asyncの中にユーザーのコードを入れるのはちょっと難しかった。 Importとかトップレベルにしかかけないものをいけないとか。
Avatar
あー、なるほどそうか。。。
9:08 AM
SwiftSyntaxでTopLevelDeclを探してやるとか、大掛かりになりそう
Avatar
Kishikawa Katsumi 2/23/2021 9:09 AM
そうですね。最初ちょっとimportだけ抜き出すとか文字列操作でやろうとしたところで、他にもいろいろありそうと思っていったんやめました。Swift Syntaxを使うでうまくできそう。
Avatar
protocolとかextensionとかトップレベルでしか書けないやつがいくつかありそうですよねー (edited)
Avatar
Kishikawa Katsumi 2/23/2021 9:16 AM
まあ現時点でいろいろ試せるようになったからこの状態でシェアしてみよう。
🎉 1
Avatar
Kishikawa Katsumi 2/23/2021 9:39 AM
We don&#39;t want people using this as a means of jumping from synchronous code to async code. It blocks the thread that it&#39;s running on and spawns a new thread to run the async code. ...
Avatar
Kishikawa Katsumi 3/4/2021 11:02 PM
StringにはRight PaddingがあるけどLeft Paddingがないんですね。両方ほしい。
Avatar
-> some View とかのようなOpaque Result Typeってオーバーライドできないですか? class Parent { func makeView() -> some View { EmptyView() } } class Child: Parent { override func makeView() -> some View { // Method does not override any method from its superclass Text("abc") } }
Avatar
へー
3:53 AM
some だから?
Avatar
これはできないで正しいと思います
Avatar
some View は一般的な View を意味するのではなく、ある特定の View の型を隠蔽して見せてないだけなので、できないと思います。
Avatar
Parentの時点でEmptyViewが返り値であるということをコンパイラは知っていて
Avatar
class Parent { func makeView() -> EmptyView { EmptyView() } } class Child: Parent { override func makeView() -> Text { Text("abc") } } ↑ができないのと同じですね。
Avatar
一方ユーザーは何もわからないので、オーバーライドできるとすると齟齬が生まれる
Avatar
うーん型を隠蔽してるだけなのはわかるのでなんとなく予想はつきましたけど、こうしてもできないのはなんでだろ 🤔 class Parent { func makeView() -> some View { Text("") } }
Avatar
型としては Parent.makeViewText を返すのはわからないので、そういうものだと思います。 (edited)
Avatar
「型を知っていればoverrideできる」なら、「最初からその型で実装すればよい」になる
Avatar
そうですね。↑をやりたい場合、どちらも戻り値の型を Text にすれば良いです。
Avatar
バグの温床「コードが知り得ない知識の利用」か
3:58 AM
実装してるもののみが知っている知識を使ってしまう
3:58 AM
どちらかっていうと、でもこの場合は逆か...?
Avatar
実装のみが知っている知識の濫用に当たると思います
3:59 AM
型には含まれていない情報なので
Avatar
(逆だとしても同じことだけど。そしてそれが阻まれてるのはよき)
Avatar
そしたらルータをDIしたい(遷移先の画面を外から注入したいとき)って、ジェネリクス以外の方法はもう AnyView 使うしかない感じです?
Avatar
意図しているイメージが合っていればジェネリクスで差し込みかAnyViewになると思いますよ (edited)
Avatar
AnyViewか…パフォーマンスどうだろ 🤔 (あまり気にするほどのものではないはずかとは思いますが
4:00 AM
ジェネリクスはちょっと画面数が多いからできれば避けたいですよね
Avatar
確かその辺iOSDCのときに青山さんに聞いた記憶があって
Avatar
omochimetaru 3/9/2021 4:01 AM
「実装者のみが知りうる知識<インプリメンターズ・ナレッジ>」厨二っぽくていいな (edited)
Avatar
AnyViewになるけどパフォーマンス劣化はそこまでひどくない感じ、みたいな話を聞いた気がする
Avatar
Avatar
omochimetaru
「実装者のみが知りうる知識<インプリメンターズ・ナレッジ>」厨二っぽくていいな (edited)
code review で「まあそのこと知ってるのはあなただけですよね」ってよくやる。
Avatar
Avatar
niw
code review で「まあそのこと知ってるのはあなただけですよね」ってよくやる。
その言葉、今度のコードレビューで使わせていただきますw
Avatar
omochimetaru 3/9/2021 4:02 AM
レビューコメント:くっ、能力者か・・・ (edited)
😅 1
Avatar
www
Avatar
SwiftUI 的にはジェネリクスでやるのがご行儀が良いとは思います。型パラ付けるの面倒ではありますが、↓みたいに。 struct Button<Label> where Label : View
Avatar
まあ本来はそのはずですが、流石に20も30ものジェネリクスがあると、みてるだけでも気が滅入るので…
Avatar
struct Router< MyItemView, MyListView, MyPreferenceView, MyUserProfileView, MyUserProfileEditView, .... > 爆誕
Avatar
そうそれ
Avatar
しんじゃう
Avatar
流石にそれは嫌だわー
Avatar
ただこれやんないと、Viewが入出力持った時に対応できないねみたいな感じになり辛くなるケースもありそう
Avatar
20, 30 の associatedtype を持った protocol 作って、 Router の型パラは一つにできないかな?ちょっと今よく考えずに発言してますが。
Avatar
となると型としてラップするガワとしてのViewの定義があればワンチャン
Avatar
AnyViewってラップするだけで内部のレイアウト変わることがあるのでげきればラップ避けれると良さそうですが・・・
Avatar
やばすぎ情報でてきた
Avatar
Avatar
Iceman
AnyViewってラップするだけで内部のレイアウト変わることがあるのでげきればラップ避けれると良さそうですが・・・
mjsk…
Avatar
omochimetaru 3/9/2021 4:07 AM
4:07 AM
イレイジャ(消すのが型だけとは言っていない)
Avatar
Avatar
Avatar
koher
20, 30 の associatedtype を持った protocol 作って、 Router の型パラは一つにできないかな?ちょっと今よく考えずに発言してますが。
それ結局何かしらの形でジェネリクスに反映されてしまいそうな気がするんですよね…
Avatar
protocol P {} struct A: P {} struct B: P {} struct C: P {} struct D: P {} protocol FooProtocol { associatedtype X: P = A associatedtype Y: P = B associatedtype Z: P = C } struct S<Foo: FooProtocol> {} struct MyFoo: FooProtocol { typealias X = D } let s: S<MyFoo> = .init() print(s) (edited)
4:12 AM
今のケースに当てはまるかわかりませんが、 associatedtype だとデフォルトの型を指定できるから楽になるとかないでしょうか?
Avatar
omochimetaru 3/9/2021 4:13 AM
使う側の型名を短くしたいだけならtypealiasは?
Avatar
あーkoherさんの言いたいことわかった気が
4:19 AM
前の実装が enum 使ってビューの出しわけをしてるのをそもそも引き継いじゃいけないんだ、そうすると確かに protocolassociatedType を具象型で隠せる
4:20 AM
(ただしMockを作るのが面倒な点は変わらないきがw
Avatar
そもそもこれ具体型のRouterを作る時に個々の実装の型を知ってなきゃいけなくて
4:21 AM
もちろんそのRouterへのアクセスする全ての個々のViewが、対象先のViewの型を知ってなきゃいけなくなるから
4:21 AM
Routerを作る目的からすると結構厳し見ありそうな予感
4:26 AM
あーまあ大丈夫か?
Avatar
よしこんな感じに落ち着かせ(ることにし)た protocol RouterObject: ObservableObject { associatedtype Login: View = EmptyView func loginView() -> Login associatedtype Home: View = EmptyView func homeView() -> Home } extension RouterObject { func loginView() -> EmptyView { EmptyView() } func homeView() -> EmptyView { EmptyView() } } final class Router: RouterObject { func loginView() -> Text { Text("Login") } } Router().loginView() Router().homeView()
Avatar
これ結局Routerを注入する側のViewでGenericsにRouterを宣言しないといけなくなりません?で、そのViewをRouterから参照しようとするとループになりそうな
Avatar
omochimetaru 3/12/2021 5:01 AM
5:01 AM
5:02 AM
Encodableのマージ、あるタイミングで SingleValueEncoder 越しにできなくなったんだけど、 Encoder 越しならできるらしい・・・
5:02 AM
知らなかった・・・
Avatar
SingleValueEncoderしか状態を持ってないのか
Avatar
割と想像可能な挙動な気もする
Avatar
omochimetaru 3/12/2021 5:04 AM
マージになるのがたまたまなのか意図された結果なのか・・・
Avatar
すくなくともEncoderの実装依存。。。
5:06 AM
https://developer.apple.com/documentation/swift/singlevalueencodingcontainer
A container that can support the storage and direct encoding of a single non-keyed value.
2回エンコードできるかどうかについては記述されてなさそう
Avatar
呼び出し先のencodeにsingleValueContainerが含まれてると死にそう
Avatar
omochimetaru 3/12/2021 5:08 AM
The Foundation Project, providing core utilities, internationalization, and OS independence - apple/swift-corelibs-foundation
5:08 AM
OSS Foundationの場合だと、 SVEC はチェックが入ってるから死んで (edited)
5:09 AM
The Foundation Project, providing core utilities, internationalization, and OS independence - apple/swift-corelibs-foundation
5:10 AM
この実装の場合経由することになる KEC は、2回目は 同じ .object を再利用するコードになっている
Avatar
前見たときとかなり実装変わってるな〜と思ったら直近で巨大リファクタリングが入ってた
5:14 AM
After #2966 and #2985, this is the last step to make JSON Encoding and Decoding much more performant on Linux.
Avatar
omochimetaru 3/12/2021 5:14 AM
8日前だね
5:16 AM
旧実装でも
5:16 AM
// If an existing keyed container was already requested, return that one.
5:17 AM
2回めのKVCの生成において、下請けのストレージ(このときは生のNSMutableDictionaryだったようだ)に同じものを返す挙動についてコメントがあるから、意図的っぽくはみえる。 (edited)
Avatar
なるほど。こんど実装することがあったら気をつけよ
Avatar
omochimetaru 3/12/2021 5:18 AM
そうするとSVECとSVDCはわざわざ経由しないほうが良いのかな。
5:18 AM
ソッチのほうが行儀が良い気がしてそうしてた。
Avatar
っぽいですね
Avatar
omochimetaru 3/12/2021 5:20 AM
アイエェ
Avatar
omochimetaru 3/12/2021 5:22 AM
いや、 func container() のなかの canEncodeNewValue は旧実装でもあって
5:22 AM
それはまた別のチェックみたい
5:23 AM
private var canEncodeNewValue: Bool { return node == .unused }
5:23 AM
YAMSのcanEncodeNewValueは別のロジックだった・・・ダメそう
Avatar
The Foundation Project, providing core utilities, internationalization, and OS independence - apple/swift-corelibs-foundation
5:28 AM
The Foundation Project, providing core utilities, internationalization, and OS independence - apple/swift-corelibs-foundation
Avatar
omochimetaru 3/12/2021 5:31 AM
さっきザッと見たけど無さそうだよね
5:32 AM
どっかで挙動が変わったら地獄が生まれそう
Avatar
omochimetaru 3/12/2021 5:33 AM
FoundationはOSに載ってるから
5:33 AM
iOSのアップデートによりアプリが落ちることになるな
Avatar
Foundationのバージョンアップで壊れるやつ、稀によくある
😩 1
Avatar
serializerで仕様がふんわりなことはよくあるし、まあなんか実際のところは雰囲気でなんとなーく動いてて、でもたまに死んだりしてでもまあレアなことだから世の中それで回ってるんだろうなあという印象
Avatar
ちょうどこの間それやったんですが、野良Encoder実装はほぼほぼ対応してない(msgpackのEncoderもだめだった)ので、どうしようもない場合を除いてやめておいたほうが無難そう (結局その時はJSONEncoderで吐いたJSONをJSONSerializationで戻してmsgpackのライブラリに食わせた)
Avatar
omochimetaru 3/12/2021 6:05 AM
JSONの場合、仕様が先に存在している場合もあるので・・・
6:07 AM
でも野良コーデックが対応してないってことは
6:07 AM
やっぱりちゃんとはっきりさせておいたほうがいいんだろうな
6:07 AM
めんどくさいな・・・
Avatar
omochimetaru 3/23/2021 5:59 AM
Pitch: SwiftPM support for Swift scripts Proposal: SE-NNNN Authors: Rahul Malik, Ankit Aggarwal, David Hart, YR Chen Review Manager: TBD Status: Awaiting implementation Introduction Swift is a general-purpose language that aims to expand its availability and impact on various domains and platforms. We believe great scripting support and expe...
6:00 AM
Swiftのスクリプティングモードの仕様の提案
6:01 AM
package.swiftのpackage指定と同じ文法で@packageをimportの上に書くという仕様で、良さそう
Avatar
SwiftでAPI公開してるプロジェクトでdelegateのprotocolに新しく追加する場合って、破壊的な変更になってしまうのってどうやって回避してるんだろう
6:45 AM
1. じつはわかってるので最初から @objc optional で公開している
Avatar
omochimetaru 3/23/2021 6:45 AM
1. @obj optional 2. extensionでデフォルト実装を与える
Avatar
2. extension でデフォルトの実装を与えてる。派生して呼べなくなってもしらない
Avatar
omochimetaru 3/23/2021 6:45 AM
3. 別名のプロトコル
Avatar
ぐぅー、そうかぁ...
Avatar
omochimetaru 3/23/2021 6:46 AM
派生して呼べなくなってもしらない
これはどういう心配ですか?
Avatar
なんだっけ、protocolを実装してるclassを派生してoverrideしても見えないってやつ
Avatar
omochimetaru 3/23/2021 6:47 AM
ああ。
Avatar
厳しい...
6:47 AM
majorバージョンあげるか...
6:47 AM
こっそりminorで破壊的な変更をするか... (行儀悪い)
Avatar
omochimetaru 3/23/2021 6:47 AM
継承元でconformしてるprotocolのメソッドと、同名のメソッドを継承先で実装したときに呼ばれないやつか
Avatar
はい
Avatar
omochimetaru 3/23/2021 6:48 AM
まず継承元で実装しましょう
Avatar
それはprotocol使う側の問題なんだよなあ...
Avatar
omochimetaru 3/23/2021 6:48 AM
使う側の問題なので提供側の態度としては問題がないのでは
Avatar
つまりextensionを与えるとそれも破壊的な変更になってしまう
6:49 AM
なかなか手厳しい
Avatar
omochimetaru 3/23/2021 6:49 AM
ライブラリとしての下位互換性はこわれてないのでは?
6:49 AM
その問題はprotocolのデフォルト実装についてまわる問題で
6:50 AM
互換性とかライブラリの話とはそもそも独立
Avatar
ああ、そうか、確かに。
6:50 AM
与えるか...
Avatar
omochimetaru 3/23/2021 6:50 AM
ポリシーとして、その問題があるからdefault実装は使わないって話なら、だめですが。
Avatar
できれば避けたいのが本音
Avatar
omochimetaru 3/23/2021 6:51 AM
そしたら別名のプロトコルにするしかなさそう
Avatar
だなあ...
Avatar
omochimetaru 3/23/2021 6:52 AM
もともとが protocol P1 だとして、 protocol P2 を導入しつつ
6:53 AM
P1からP2に変換するアダプタを用意してライブラリ内部はP2に書き換える、P1からのインターフェースはアダプタかますようにして互換性を保つ。
Avatar
なんらかそう言うのが必要になりますね...
6:57 AM
delegate2
Avatar
omochimetaru 3/23/2021 6:57 AM
Creates an overlapped, pop-up, or child window with an extended window style; otherwise, this function is identical to the CreateWindow function.
Avatar
A/Wは文字のやつじゃなかったっけ
Avatar
omochimetaru 3/23/2021 6:58 AM
Enumerates calendar information for a locale specified by name.Note  The application should call this function in preference to EnumCalendarInfo or EnumCalendarInfoEx if designed to run only on Windows Vista and later. Note  This function can enumerate data that changes between releases, for example, due to a custom locale. If your application m...
Avatar
Exの部分か
6:58 AM
ExEx w
Avatar
omochimetaru 3/23/2021 6:58 AM
Exの部分です
6:58 AM
無限に伸ばせるぞい
Avatar
delegatex
Avatar
基本delegateパターンは@objc optionalが無難な気はします
6:59 AM
無理に純swiftにする必要はなくて、純swiftの必要があるならdelegateよりは各所handler渡しにしちゃった方が良い (edited)
Avatar
omochimetaru 3/23/2021 7:01 AM
それはあるな。
7:02 AM
自分はdelegateパターンってそもそもSwiftで使わなくて、必要なだけ関数型のプロパティをセットさせるようにしているから
7:02 AM
今回みたいなコールバックの追加の際はプロパティが増えるだけ
Avatar
まあそうなんですよねー
7:02 AM
失敗した
7:02 AM
学びがある
Avatar
omochimetaru 3/23/2021 7:02 AM
delegateパターンのほうが嬉しいのはそもそもObjCにクロージャがなかった頃に使いやすいやりかただったからということを踏まえると
Avatar
0.1にしておけばよかった
😇 1
Avatar
omochimetaru 3/23/2021 7:02 AM
delegateパターンを提供するんであれば最初から @objc にしてしまってもよい
Avatar
まあしばらくはdelegate追加とextensionのdefault動作でごまかして2に早めに移行かなあ... (edited)
Avatar
delegateパターンは個別handler全部入りを渡すわけで、そもoptionalじゃないとキツいし、分けて実装したいみたいなときに不便で個人的には好きではなかったり
7:09 AM
あとデフォルト実装のは、それがoptionalであることを明示できないので、あんまり良くないかなと思いました (edited)
Avatar
blockがclangに追加されたときにAppleのAPIがやたらめったらhandlerを使うようになったんだけど
7:15 AM
次第に嫌われてdelegateに戻っていた過去があるんですよねえ...
7:16 AM
Swiftはまた別だけど。
Avatar
純swiftのライブラリとして出すならhandler、objcからも使えるならdelegateでも良くて、そうした場合は@objcつけるのがベストな気はする (edited)
Avatar
多分、retain cycleへの備えが爆発的に増えて厳しかったんじゃないかなあと思う
Avatar
block出たときはもうweakあったから、ちゃんとしてないだけでは…と思ったけどそれはそれで
Avatar
ちゃんとするのが難しいのは変わらないからなあ...
Avatar
swiftはweak指定がobjcよりは遙かに楽なので
Avatar
omochimetaru 3/23/2021 7:18 AM
そんな変わるっけ?
Avatar
@weakifyマクロとかありましたねObjC しんどかった印象 (edited)
Avatar
omochimetaru 3/23/2021 7:18 AM
objcも __weak とかじゃなかたっけ
Avatar
swiftはキャプチャ構文とguard letがあって遙かに楽
Avatar
omochimetaru 3/23/2021 7:20 AM
あーキャプチャブロックがないし型推論がないからローカル変数で型名書き直さないといけないのか。
Avatar
__weak typeof (self) weakSelf = self; void (^const block)(void) = ^{ typeof (self) const strongSelf = weakSlef; if (!strongSelf) { return }; };
7:21 AM
これですよね
Avatar
それそれ
Avatar
10000回は補完してる
Avatar
omochimetaru 3/23/2021 7:22 AM
typeofなるほど
Avatar
{ [weak self] in guard let self = self else { return } }
7:22 AM
簡単
7:23 AM
でもまあ本質的には変わらなくて、
7:23 AM
やっぱり retain cycle への備えみたいなのが厳しい印象ある
Avatar
omochimetaru 3/23/2021 5:23 PM
The review of SE-0295 - Codable Synthesis for enums with Associated Values has concluded and the proposal is accepted. You can find the 1st and 2nd rounds of reviews here and here respectively. There was general consensus that the solution would help a number of users, even if the encoding was not unanimously agreed upon. The core team does n...
5:23 PM
enumのCodableサポートが通ったぞう
5:24 PM
Hello folks, Common feedback during the review of SE–0295, and over the years since the introduction of Codable, is that Codable is not flexible or customizable enough to address all serialization needs. The core team felt it was important to share that while Codable plays a critical role in the Swift ecosystem, the core team does not see Coda...
5:24 PM
合わせて、Codableの将来について意見を募るスレッドが立っていて、いろんな意見が書き込まれてる
5:25 PM
>>47 の BackedCodable はなかなかおもしろい https://github.com/jegnux/BackedCodable
Powerful property wrapper to back codable properties. - jegnux/BackedCodable
5:26 PM
enumのCodable対応には苦労していて、コードの自動生成したりもしてたから、0295はとても助かる
Avatar
Kishikawa Katsumi 3/28/2021 1:00 PM
https://async-await-in-swift.netlify.app/ PlaygroundをEmbedできるようにして動くドキュメント(チュートリアル?)みたいなの作れるようにしてみた。 (edited)
👁️ 1
1:01 PM
なんかもっとうまく書いてくれる人が書いてくれるとめっちゃいい感じになると思うのだが。。。
Avatar
おお?
8:25 PM
'runAsyncAndBlock' is deprecated
8:26 PM
.playground をHTMLに埋め込む感じ?
Avatar
Kishikawa Katsumi 3/29/2021 1:09 AM
はい。iframeで埋め込んだときの体裁を整えました。 ^ のソースコードは https://github.com/kishikawakatsumi/async-await-in-swift/blob/main/index.html
Contribute to kishikawakatsumi/async-await-in-swift development by creating an account on GitHub.
Avatar
Kishikawa Katsumi 3/29/2021 1:24 AM
<iframe class="code-snippet-sm" src="https://swiftfiddle.com/txdtgymelzddre63gl2dv5wori/embedded/" frameborder="0"></iframe>
1:25 AM
みたいな。
Avatar
omochimetaru 3/30/2021 6:29 PM
The third review of SE-0293 has concluded. Feedback in the third round of review was quite positive, a result of the great iteration from the previous rounds of proposal. As such, the core team has accepted the proposal as written. Thank you to the proposal authors and to the community for the discussion and iteration, and for helping make Sw...
6:30 PM
パラメータ部分にwrapperつけられるやつ決着した
Avatar
今年のWWDCは言語面だけでも盛り沢山になりそうですね🤩
Avatar
Kishikawa Katsumi 3/31/2021 2:34 PM
The review of SE-0307, "Allow interchangeable use of CGFloat and Double types", begins now and runs through March 24, 2021. The proposal is authored by @xedin. 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 ...
Avatar
omochimetaru 3/31/2021 7:09 PM
また一つ暗黙の型変換が増えた
7:10 PM
とはいえ、ま~これは便利だし実害もあんまり無い気がする。
Avatar
こわい
7:14 PM
implicit こわい
Avatar
omochimetaru 3/31/2021 7:15 PM
32bit環境がほぼ実在しないので
Avatar
Windows 「え?」
Avatar
omochimetaru 3/31/2021 7:41 PM
WindowsにCore Graphics無いから大丈夫
Avatar
swift-corelibs-foundation にあるから 32bit CGFloat は実在はする。
Avatar
けど今回のはランタイムは一切関わらずルールに従ってコンパイラが暗黙的に変換を埋め込むだけだから、リスクは低そう。 つまり、 let a: CGFloat = 1.0 let b: Double = a + 1.0 が、 let b: Double = Double(a) + 1.0 に書き換えられるだけ。実行時暗黙変換はしないので下記は失敗する。 let a: Any = CGFloat(1.0) let b: Double = a as! Double
Avatar
Kishikawa Katsumi 3/31/2021 9:48 PM
Double => CGFloatは大丈夫なんだろうかと思ったけど既存のコードはすべてコード上で自分で変換してるわけだから知らないうちに問題が起こることはないのね。
Avatar
https://forums.swift.org/t/se-0308-if-for-postfix-member-expressions/47163 #if の機能を拡張するプロポーザルがレビューに入りました。 Text("title") #if os(iOS) .iOSSpecificModifier() #endif .commonModifier() みたいなのを出来るようにする提案です。
The review of SE-0308, "#if for postfix member expressions, begins now and runs through April 16, 2021. The proposal is authored by @rintaro. 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...
👏 3
Avatar
Kishikawa Katsumi 4/5/2021 4:27 PM
これはいいですね。 #if os(iOS) func button() -> UIButton { #else func button() -> NSButton { #endif ... } こういうのは無理なのかな?
Avatar
それはまだダメですね。今のところ typealias で対応する必要があると思います。
4:31 PM
#if canImport(UIKit) typealias ButtonType = UIButton #elseif canImport(AppKit) typealias ButtonType = NSButton #else #error("UIKit or AppKit is required") #endif
Avatar
Kishikawa Katsumi 4/5/2021 4:34 PM
まあそれとは別の問題という感じある。 Proposalの提案ができるようになるだけでもだいぶ見やすく書けそう。 (edited)
👍 1
Avatar
omochimetaru 4/5/2021 6:04 PM
このメソッドチェーンの一箇所だけ #if で付け外しできるの便利だけど、 コンパイル時の #if 文だとできるのに普通の実行時の if 文じゃできないのが逆に不満に感じるようになりそう
6:06 PM
今までは #if は式の途中に差し込むことはできなかった(?)から、 カットできるのは文の単位だから、普通の if 文とコードの形的にはほぼ同じ機能だった(?)気がする けど これが出てくると #if の方が強くなってしまう まあ別に便利だからそれ自体はいいんだけど
Avatar
Kishikawa Katsumi 4/5/2021 6:06 PM
それは思う。SwiftUIだと普通のifもチェーンの途中で割り込みたいことよくある。
Avatar
omochimetaru 4/5/2021 6:07 PM
そうですよね。Motivation sectionで os(iOS) って条件文を書いてるけど、そうじゃなくて動的な条件でも同じことがしたいことがありそう。 まあSwiftUIだと式の型まで影響を受けるから厳しそうだけど
Avatar
Kishikawa Katsumi 4/5/2021 6:10 PM
前あったのはこういうケースでした。 if widgetFamily == WidgetFamily.systemSmall { Link(destination: Self.endpoint(APIKey: entry.configuration.APIKey, deviceID: entry.configuration.deviceID )) { Label("", systemImage: "lock.fill") .frame(minWidth: 0, maxWidth: .infinity) .font(.headline) .padding(.trailing, -8) .padding(.all, 16) .background(Color.gray.opacity(0.2)) .clipShape(Capsule()) .offset(CGSize(width: 0, height: 6)) } } else { Link(destination: Self.endpoint(APIKey: entry.configuration.APIKey, deviceID: entry.configuration.deviceID) { Label("Unlock", systemImage: "lock.open.fill") .frame(minWidth: 0, maxWidth: .infinity) .font(.headline) .padding(.all, 16) .padding(.all, 0) .background(Color.gray.opacity(0.2)) .clipShape(Capsule()) .offset(CGSize(width: 0, height: 6)) } }
6:11 PM
SwiftUIは意外とModifierチェーンの順序も影響するから途中だけ違うっていうのが難しいんすよね。順序が影響しなかったら共通部分だけ変数に入れてそこからModifierを分岐ってするのがいいと思うけど。
6:12 PM
まあこの例はもしかしたら順序関係なくいける気もする (edited)
Avatar
omochimetaru 4/5/2021 6:13 PM
この具体例に限れば、オペレータの並び順自体は一緒だから、パラメータの部分を個別に分岐するか、 パラメータ達だけ先にletで組んでおくって書き方はできそうですね。 でも言いたいことはわかります。
Avatar
Kishikawa Katsumi 4/5/2021 6:15 PM
どれがわかりやすいかはケースバイケースになって難しいんですよね。この場合はModifireの形が一緒だからifで複数書かない方がわかりやすいと思って違う部分だけ三項演算子で書いたんですが、違う部分を変数にしとくってのも良さそう。 ただチェーンにIfが割り込めたら多分それはベストっぽい。
Avatar
if演算子があれば目的が達成できそうで、メソッドチェーンのためにif文そのものを拡張するのはやりすぎかなと思いました
6:27 PM
例えば Link(destination: ...) { Label(...) .if(condition) { $0.color(...).... } else: { $0.color(...).... } .font(...) } の様な。 後岸川さんの例は、Linkのclosureの中でifでEitherView<...<Label>,...<Label>>に出来そうな気がする。 (edited)
Avatar
こんな感じか? struct If<Then: View, Else: View>: ViewModifier { var condition: () -> Bool var `then`: (Content) -> Then var `else`: (Content) -> Else func body(content: Content) -> some View { if (condition()) { self.then(content) } else { self.else(content) } } } extension View { func `if`<Then: View, Else: View>( _ condition: @escaping @autoclosure () -> Bool, then: @escaping (If<Then, Else>.Content) -> Then, else: @escaping (If<Then, Else>.Content) -> Else ) -> some View { modifier(If(condition: condition, then: `then`, else: `else`)) } } (edited)
Avatar
omochimetaru 4/5/2021 6:34 PM
なるほど〜たしかに。
Avatar
#available(iOS 14, *) とかが使え無いのが残念ではありますね。
Avatar
omochimetaru 4/5/2021 6:38 PM
あー、自作if文ってそういう弱みがあるのか
Avatar
Kishikawa Katsumi 4/5/2021 6:45 PM
なるほど。これは良さそうだな。
Avatar
Kishikawa Katsumi 4/5/2021 11:00 PM
https://swift.org/blog/swift-collections/ OrderedSetとかOrderedDictionaryとか。めっちゃいい。
I’m thrilled to announce Swift Collections, a new open-source package focused on extending the set of available Swift data structures. Like the Swift Algorithms and Swift Numerics packages before it, we’re releasing Swift Collections to help incubate new functionality for the Swift Standard Library.
Avatar
omochimetaru 4/6/2021 4:02 AM
ODほしくて自作した事もあるぐらいだから助かる c++より少し早いの凄いな
Avatar
omochimetaru 4/6/2021 4:45 AM
Dequeだけでもかなり凝った実装してるなあ
Avatar
yutailang0119 4/6/2021 4:48 AM
Numericとかもだけど、今後は基本Foundationじゃなくて個々にOSSリポジトリが作られてく感じなのかな
Avatar
omochimetaru 4/6/2021 4:49 AM
そうっぽいですね。まあ、Foundationでやっていくと、Server Side Linuxとか進まないですし。
Avatar
Deque 前に作ったからどんな実装してるのかと気になって見てみたけど、標準ライブラリに ManagedBuffer とかあったのか。これ使えば自前の実装からコード削減できそう。 https://developer.apple.com/documentation/swift/managedbuffer
Avatar
omochimetaru 4/6/2021 5:03 AM
ManagedBufferはコード量削減というより
5:03 AM
tail-allocatedなデータ構造を作るためのヘルパーですね
5:04 AM
たしかSwift.ArrayやSwift.Stringだと使ってなくて同じ事を自力でやっていて
Avatar
いや、多分これに相当する機能を自作してたから、それを削減できそう。
Avatar
omochimetaru 4/6/2021 5:04 AM
ManagedBufferの立ち位置微妙だな〜と思ってたんですが、このライブラリだとこれをしっかり活用していてよかった
5:04 AM
なるほど。
5:05 AM
自作するとかなりunsafe APIを駆使したコードになっていそう。 (edited)
Avatar
はい、 Unsafe 使ったコードになってます。
5:07 AM
あと、 append に対応する先頭への追加は prepend になるのかぁ。わからんかったから appendFirst にしてしまった。
Avatar
omochimetaru 4/6/2021 5:13 AM
整数が扱えるだけの _HashTable があって、 OrderedSet_HashTableContiguousArray をもっていて、 要素はArrayにいれといて、 _HashTable は値から配列のインデックスを逆引きできるように同期しているっぽい。
5:15 AM
OrderedDictionaryOrderedSet<Key>ContiguousArray<Value> をもっていて、 2つのインデックスは揃えてあるっぽい。
5:17 AM
DequeもHashTableも Storage の実装に ManagedBuffer を使ってますね。 ただDequeのほうはStorageをstructにしてあって Storageが ManagedBufferPointer を使って ManagedBuffer を所有していて更にややこしい
Avatar
Avatar
rintaro
#available(iOS 14, *) とかが使え無いのが残念ではありますね。
#available 使えない問題に関してはif modifierなんて作らずに、こんなので良い気がしてきた。 extension View { func map<Result: View>(@ViewBuilder _ transform: (Self) -> Result) -> Result { transform(self) } } Text("test") .map { if #available(iOS 14, *) { $0.ignoresSafeArea() } else { $0.self } } (edited)
Avatar
めっちゃいい
6:51 AM
というか基本的にif式ほしいときはこのアプローチでいいんですよね。if式が使えるコンテキストを開く関数が1個あれば
Avatar
omochimetaru 4/6/2021 6:51 AM
mapの中もViewBuilderで、型は伝搬できるのか
Avatar
SwiftUIに限らずだいたいなんとでもなる
Avatar
これ型あわせないといけなくて大変なんじゃって思ったけどViewBuilderついてるからConditionalContentになるのか
Avatar
omochimetaru 4/6/2021 6:53 AM
mapってかletだな〜
☝️ 2
6:54 AM
式を名前に束縛してスコープを作ってるから。
Avatar
なるほど let か、多分 map じゃないよなーと思いながらとりあえず出してみたのです。
😀 1
Avatar
let関数に相当するのって、他の言語だとどういう名前になるんだろ
9:20 AM
帯域でlet関数に相当するものを作っておくと便利なんだけど、let が予約語なので使えないんだよな
9:20 AM
kotlinはまさにletで、 Anyに対するextension methodだよ
Avatar
Any
9:20 AM
に対してのextensionはできないので
Avatar
omochimetaru 4/6/2021 9:20 AM
定数(というかreadonlyだけど)宣言は val を使う
9:21 AM
Swiftはできないね。> extension Any
Avatar
if/switch/(xcode12.5でwhile/for)を式として使えるスコープをパパっと作る関数を定義したくて
9:21 AM
なんか型推論の魔法使えて
9:22 AM
LCTを指定したらその型に、そうでない場合は近傍のEitherに収束する関数ができた
👀 1
9:22 AM
同じ型ならその型になる。
Avatar
omochimetaru 4/6/2021 9:22 AM
protocol Lettable { func `let`<R>(_ f: (Self) throws -> R) rethrows -> R } extension Lettable { func `let`<R>(_ f: (Self) throws -> R) rethrows -> R { try f(self) } } struct S: Lettable { } S().let { print($0) }
Avatar
それだとEitherにしたいときに不便なんだよね。なので
Avatar
omochimetaru 4/6/2021 9:23 AM
Lettableつけた型なら使える ってスタイルならできる
Avatar
let a = xxx { if cond { 1 } else { "" } } // Either<Int, String> let b = xxx { if cond { 1 } else { 2 } } // Int let c = xxx { if cond { Cat() } else { Dog() } } // Either<Cat, Dog> let d: Animal = xxx { if cond { Cat() } else { Dog() } } // Animal こういうのが出来た。 (edited)
Avatar
omochimetaru 4/6/2021 9:25 AM
Eitherに対して .leastCommon ってプロパティがあればいいような気も?
Avatar
xxxの名前は何がいいかな〜って感じ
9:25 AM
いやそれは無理なんだよね
Avatar
omochimetaru 4/6/2021 9:26 AM
汎用のResultBuilderを使って式スタイルを使いたいって感じの機能だから、 名前をつけるなら expressive とか?
Avatar
このxxxの関数の嬉しいところは、左辺で型が束縛されていればよしなに解決されるし、でなければEitherで出てくるし、全部同じ型ならそのままの型で使える
9:27 AM
まあそんな感じですかね
9:27 AM
tx
Avatar
omochimetaru 4/6/2021 9:27 AM
うーん、その2つは別名でいいのでは
9:27 AM
推論に頼るとユーザーの想定と違う挙動して混乱する事もありそう
Avatar
gistにポン置きする30行程度のメモ書きだからよしなに書き換えたらいいと思うよ。
Avatar
omochimetaru 4/6/2021 9:33 AM
いやそれは無理なんだよね
これはどういう無理?不便ってこと?実装上?
Avatar
実装上不可能です。EitherのL, Rを判定して計算されたLCTを出す、というのが
9:34 AM
are
9:34 AM
できるかもしれねぇ
9:34 AM
あでも、だめだ
9:34 AM
Either<Either<A, B>, C> が解けない
9:34 AM
ResultBuilderだとこれが解けるようになる
Avatar
omochimetaru 4/6/2021 9:37 AM
9:37 AM
親クラスって成約につかえないのか
Avatar
ネストしてなくてもだめだったか。
9:40 AM
ネストしてる場合は完全に無理なんで
Avatar
omochimetaru 4/6/2021 9:41 AM
パラメータとして与えられた型を制約にするのって無理なんだな あくまで最初から静的にプロトコル名を与えないといけないのか (edited)
9:41 AM
あ、いや、そうか・・・
9:43 AM
enum Either<L, R> { case left(L) case right(R) } extension Either { func join<C>( type: C.Type = C.self, left: (L) -> C, right: (R) -> C ) -> C { switch self { case .left(let x): return left(x) case .right(let x): return right(x) } } } class Animal {} final class Cat: Animal {} final class Dog: Animal {} func main(_ x: Either<Cat, Dog>) -> Animal { x.join { $0 } right: { $0 } }
9:44 AM
class Animal {} final class Cat: Animal {} final class Dog: Animal {} final class Bird: Animal {} func main(_ x: Either<Cat, Dog>) -> Animal { x.join { $0 } right: { $0 } } func main2(_ x: Either<Either<Cat, Dog>, Bird>) -> Animal { x.join { $0.join { $0 } right: { $0 } } right: { $0 } }
Avatar
なかなかにしぶい
9:45 AM
私の型マジック付きコードだと
Avatar
omochimetaru 4/6/2021 9:45 AM
main2 がネストしてる場合。意味のない { $0 } が必要になっちゃった。
9:45 AM
RxSwift使ってて意味のない .map { $0 } があると思ったら T から T? にキャストしてるやつを思い出した。
9:46 AM
この意味のない { $0 } を推論器からデフォルトの値として生成させられたらベストだけど多分ないんだろうな
Avatar
let x = expressive { if cond1 { Cat() } else if cond2 { Dog() } else { Bird() } } // Either<Either<Cat, Dog>, Bird> let y: Animal = expressive { if cond1 { Cat() } else if cond2 { Dog() } else { Bird() } } // Animal になるので、なかなかに便利だよ
Avatar
omochimetaru 4/6/2021 9:48 AM
buildExpressionとかがオーバーロードできるからできるのかな?
Avatar
buildEitherをオーバーロードして
Avatar
omochimetaru 4/6/2021 9:49 AM
buildEitherか。
Avatar
@_disfavoredOverload でEitherの順位を下げるとこうなる
Avatar
omochimetaru 4/6/2021 9:49 AM
ズル
💪 1
9:49 AM
曖昧なケース出ちゃう気がしたけど disfavored・・・たしかに・・・ (edited)
Avatar
天才っしょ
Avatar
omochimetaru 4/6/2021 9:50 AM
ただ式が内包してるifの数だけそのbuildEitherの選択があるから推論計算量が爆発しそうだな
Avatar
午前4時頃思いついた
Avatar
omochimetaru 4/6/2021 9:50 AM
でもまあそうやって局所的に使うなら問題ないかも。
Avatar
expressiveで閉じてるから多分大丈夫
Avatar
https://gist.github.com/tarunon/c45d76d8be9d01ce0ea074b69a586d6f とりあえず。swift5.4だと @_disfavoredOverload は要らなかった。
Introducing if statement for statement into swift. Required swift 5.4. - Expressive.swift
3:22 PM
@basashi ResultBuilderを使ってクロージャ内限定ですがif式を実現してみたので、興味があればご覧ください。 (edited)
Avatar
Kishikawa Katsumi 4/7/2021 6:31 AM
Swift CollectionsにLinkedListほしいと思ったけどDequeがそのポジションなのかな。
6:32 AM
Dequeはランダムアクセスも十分速いっぽい。
Avatar
omochimetaru 4/7/2021 6:32 AM
Dequeは先頭と末尾への追加挿入がO(1)なのが便利なコレクションです
6:32 AM
LinkedListは挿入と削除がどこでもO(1)の代わりにランダムアクセスができないコレクションです
Avatar
Kishikawa Katsumi 4/7/2021 6:32 AM
先頭と末尾か。
6:32 AM
確かにそれはちょっと違うな。LinkedListは別に欲しいな。
Avatar
omochimetaru 4/7/2021 6:33 AM
そうですね。LinkedListは需要があると思う。手書きするのもちょっとややこしいし。
6:34 AM
OrderedSet and OrderedDictionary work great when we need to keep their elements in the order they were inserted, or if we only need to infrequently reorder/sort them. However, inserting (or removin...
Avatar
Kishikawa Katsumi 4/7/2021 6:34 AM
そうそう。 書いてもいいけど、微妙に毎回デザインに迷って困るみたいな。
Avatar
omochimetaru 4/7/2021 6:34 AM
@koher が書いていたSortedSetはissueになっているな。Lorenteyさん本人で。
Avatar
Kishikawa Katsumi 4/7/2021 6:35 AM
Bagとかも構想にあるのかな。
6:35 AM
Multimapってなんだっけ?
6:35 AM
重複するキーを許すDictionaryか。
Avatar
omochimetaru 4/7/2021 6:35 AM
valueがn個のやつかな?
6:36 AM
ああそうか、Dictionary<Key, Array<Value>> だと駄目なのか。
6:36 AM
Key-Valueのペア自体がOrderedだから。
Avatar
勝手に追加されるやつね
Avatar
LinkedListは挿入と削除がどこでもO(1)の代わりにランダムアクセスができないコレクションです
挿入・削除が O(1) だけどそこまでアクセスするのが O(N) だからかなり用途が限定されませんか?事前にイテレートして同じ箇所に挿入削除を繰り返すとかでなければ。
Avatar
omochimetaru 4/7/2021 6:39 AM
典型的なユースケースとしてはメモリアロケーターがありますね
6:40 AM
確保したメモリ領域をコレクションで管理しておきたくて、解放されたらそれをコレクションから除去したい
Avatar
Kishikawa Katsumi 4/7/2021 6:40 AM
あとLRUキャッシュはLinkedListよく使いますね。
Avatar
omochimetaru 4/7/2021 6:42 AM
たしかに。キャッシュは高速化のための仕組みだしキャッシュアウトするときにO(n)で削除してパフォーマンスロストするの気持ち悪いですね。
Avatar
どちらも一般的な Sequence 準拠の Linked List を超えたノード操作が行えないときつくないですか? Iterator にそういう役目を負わせればいいのかな・・・。
6:45 AM
Value Semantics も考えるときつそう。
Avatar
omochimetaru 4/7/2021 6:46 AM
iterator.remove()が一般的かな?
Avatar
Swift の Value Semantic な世界観では無理じゃない?
Avatar
omochimetaru 4/7/2021 6:47 AM
なぜ?
Avatar
iterator に対する操作がその iterator の生成元の list に影響を与えてはいけないんじゃないかな?
Avatar
omochimetaru 4/7/2021 6:48 AM
そんなことは特に無いきがしますよ
6:48 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
6:48 AM
makeIterator がそもそも consuming なので
Avatar
Kishikawa Katsumi 4/7/2021 6:48 AM
だいたいLinkedListは要素自身から前後の要素を辿れるように作ると便利ですけどそういう話ですか?(超えているというのは)
Avatar
omochimetaru 4/7/2021 6:51 AM
いや、consumingは関係ないか・・・ 元のコレクションを見たら削除されているという状態がほしいのだから・・・
Avatar
だいたいLinkedListは要素自身から前後の要素を辿れるように作ると便利ですけどそういう話ですか?(超えているというのは)
前後を知っているのは Element ではなくそれを包むノードのはずなので、 Element を扱う Sequence の枠組みを超えたところでないと、あるノードから操作を開始して前後のノードをつなぐみたいな操作はできないのかなと。
Avatar
omochimetaru 4/7/2021 6:54 AM
それはそうですね。
6:54 AM
SwiftだとCollection.Indexがノードと対応する気がします。
6:54 AM
IndexはStridableとかも要求してて駄目か?
Avatar
あー、 Index をノードにするのはいい案かも?
Avatar
omochimetaru 4/7/2021 6:55 AM
なんか以前この辺を悩みながら実装してウーンとなった記憶があるな
6:56 AM
6:56 AM
思い出した
6:57 AM
Collection.Indexが Comparableを要求するんですけど
6:57 AM
LinkedList.NodeをIndexとさせようとしても
6:57 AM
あるNode2つの間の前後関係の検査に
6:57 AM
O(n)が必要になってしまうんですよ。
6:58 AM
RangeReplacableCollection.remove(at i: Index) のシグネチャには綺麗にハマるんですけどね。
Avatar
まあ、 Collection に乗せずに似た仕組みを採用することはできるね。
Avatar
omochimetaru 4/7/2021 6:59 AM
Collection.Index.< が O(1) でなければならないという文書は見つからなかったのでギリギリセーフなんですけど、
6:59 AM
ま〜罠でしかないし・・・
7:00 AM
Collectionと似て非なるものが必要ですね。
Avatar
Value Semantics も COW で実現できそうだけど、 struct LinkedList とノードの間に class Buffer みたいなのがあって、ノードから Buffer へ弱参照持ってるとかじゃないとユニーク参照か調べられなさそうな気が。
Avatar
omochimetaru 4/7/2021 7:05 AM
そうですね。僕の↑の実装はCoWをやってます
7:05 AM
そのへんの都合でノードからコレクションへの弱参照を持たせてます。
7:07 AM
全ノードがコレクションへのポインタを持ってるのはメモリ効率が良くないのでいけてないんですが
7:07 AM
その時は解決策が思いつかなかった。
Avatar
ああ、 LinkedListObject の外側に LinkedList があるのか。とすると LinkedListObject が僕の言っている Buffer に相当しますね。
Avatar
omochimetaru 4/7/2021 7:11 AM
そう。
7:11 AM
LinkedListObject直接使っても良いようになっている
Avatar
思ったんだけど、クラスでも mutating func が使えたら、 self 書き換えで COW で Value Semantics 実現できないかな?例の、プロトコルを使った class の mutating func という黒魔術が・・・。
Avatar
omochimetaru 4/7/2021 7:13 AM
えっと
7:13 AM
外側がクラスだと
7:13 AM
外側のクラス自体が共有されているので
7:14 AM
内側のストレージクラスへの参照は常に1だから
Avatar
いや、外側をなくす
Avatar
omochimetaru 4/7/2021 7:14 AM
複製するタイミングが判定できない?
7:14 AM
あーそれはできますね
Avatar
LinkedListObjectclass LinkedList にして
Avatar
omochimetaru 4/7/2021 7:15 AM
self書き換えがprotocol越しにしかできないのと
Avatar
クラスの mutating func って意味あるのかって話があったけど、これ結構おもしろいユースケースじゃないかな?
Avatar
omochimetaru 4/7/2021 7:15 AM
classなのにvarで使わないといけないけど。
7:16 AM
うーんでもそもそも
7:16 AM
CoWが便利なのは
7:16 AM
structでそもそも var a = b が bからaへのコピーに見えるのが遅延できるという話であって
7:16 AM
classの var a = b はそもそも共有に見えているので
7:16 AM
共有だと思ったら実体が増殖して分裂するという挙動になってしまって
7:17 AM
structのコピーのようにコピーしたかのように振る舞うclass
7:17 AM
になって何がなにやら
Avatar
まあこれまでの常識からするとややこしいけど、 struct のように振る舞う class を作れるということになる。
Avatar
omochimetaru 4/7/2021 7:18 AM
そうですね。ただ、protocol越しの裏技が必要だから
7:18 AM
ユーザーからするとprotocol型で扱うので
7:19 AM
やっぱりそもそもstructに見えてますよ
Avatar
SwiftUIよろしくstructでラップしておくのがユーザーには親切かな
Avatar
@swift-5.3.3 protocol MutableCollection { associatedtype Element mutating func append(_ element: Element) } protocol _LinkedList: MutableCollection { init(_: Self) } extension _LinkedList { mutating func append(_ element: Element) { self = .init(self) } } final class LinkedList<Element>: _LinkedList { typealias Element = Element init() {} init(_: LinkedList<Element>) {} } var list: LinkedList<Int> = .init() print(ObjectIdentifier(list)) list.append(42) print(ObjectIdentifier(list))
Avatar
swift53 BOT 4/7/2021 7:24 AM
ObjectIdentifier(0x0000000009ecd880) ObjectIdentifier(0x0000000009e4ff50)
Avatar
ユーザーからするとprotocol型で扱うので
これはなくてもいけそう。
Avatar
omochimetaru 4/7/2021 7:25 AM
あれ?そうか、そうなるのか。
Avatar
ちなみに var list let list にするとコンパイルエラーなので完全に値型っぽく振る舞ってる。 (edited)
Avatar
omochimetaru 4/7/2021 7:25 AM
let list だとコンパイルエラー」ですかね? (edited)
Avatar
ああ、間違えた。
Avatar
omochimetaru 4/7/2021 7:26 AM
おもろいな、これ。
Avatar
もし、これができるならクラスに mutating func を開放してもよいと考えるなら、プロトコルの黒魔術も要らないね。これまではユースケースが思いつかなかったけど、 COW で Value Semantics を持ったクラスというのはおもしろい気がする。ややこしいけど。
Avatar
omochimetaru 4/7/2021 7:28 AM
言語の設計的にはclassにmutating funcを開放する事自体は特に問題無さそうですね
7:30 AM
あ、でもそうなると、今度は、プロパティの変更の有無とmutatingの検査が必要になって
7:30 AM
既存のclassのコードは壊れるな。
Avatar
いや、クラスではプロパティの変更は mutating によらない。
Avatar
omochimetaru 4/7/2021 7:30 AM
あくまでself書き換えだけをコントロールするって意味ですか?
Avatar
self の書き換えができるかどうかだけが mutating による。
Avatar
omochimetaru 4/7/2021 7:31 AM
あーまあ、structの場合もそういう風に考えられるのか。
7:31 AM
structだからselfにpropertyが含まれているからであって
Avatar
そうそう。
Avatar
omochimetaru 4/7/2021 7:31 AM
classはselfが書き換わるかどうかとpropertyのmutabilityは関係ないと
7:32 AM
なるほど。理屈はあってそうw
Avatar
ややこしいけど、理論上はきれいにおさまるよねw
7:33 AM
Linked List の例付きで Forum で聞いてみたらどんな反応得られるかなぁ。今忙しいけど、落ち着いたら書いてみよかな・・・。
Avatar
Avatar
tarunon
@basashi ResultBuilderを使ってクロージャ内限定ですがif式を実現してみたので、興味があればご覧ください。 (edited)
わざわざありがとうございます。拝見させていただきます。
Avatar
extension Either: Publisher where L: Publisher, R: Publisher, L.Failure == R.Failure { public typealias Output = Either<L.Output, R.Output> public typealias Failure = L.Failure public func receive<S>(subscriber: S) where S : Subscriber, L.Failure == S.Failure, Either<L.Output, R.Output> == S.Input { switch self { case .left(let left): return left .map(Output.left) .subscribe(subscriber) case .right(let right): return right .map(Output.right) .subscribe(subscriber) } } } EitherをPublisherにして public extension Publisher { func flatMap<T, P>(maxPublishers: Subscribers.Demand = .unlimited, @Expressive<P> transform: @escaping (Self.Output) -> P) -> Publishers.FlatMap<P, Self> where T == P.Output, P : Publisher, Self.Failure == P.Failure { self.flatMap(maxPublishers: maxPublishers, transform) } } こうするじゃろ myPublisher.flatMap { value in if value.isNantoka() { URLSession.shared.dataTaskPublisher(for: hitotsumenoAPI).mapError(...) } else { URLSession.shared.dataTaskPublisher(for: futatsumenoAPI).mapError(...) } } flatMapの中でif文が使えるようになるんじゃ
12:17 PM
combineの書き味を良くするのに、ResultBuilderを使って色々ハックができる (edited)
12:18 PM
型推論をめちゃくちゃ強化するツールでもあるので、いろんなことが出来る
Avatar
丁度全く同じものを先週書いてた
Avatar
flatMapとreducer, scanあたりの型推論をバキバキに強化出来るね
12:19 PM
しかもこれ、下手するとコンパイラに優しいんじゃないか?だめだったりするかの
12:19 PM
(実用はしていないのでわからん)
Avatar
若干の懸念点として、内部でthrowできない、guard書けないという欠点がありました
Avatar
throw/guardは確かに、使えないね
Avatar
レスポンスをデコードした際のエラーを独自のエラー型にラップしようとしてスッと書けなかったので一旦諦めたけど、その処理をラップするPublisherを定義すればできそうではある
12:22 PM
コンパイラに優しいかどうかはわからんですが、型推論は若干省略がより効く気がしますね
Avatar
flatMapは、クロージャ側の型と外側の型との狭間で型が確定する、そのうちの内側の型はreturnの数だけ推論とチェックが走ってしまう が、ResultBuilderを挟むことで、内側の型は一意に決定するので、確実に優しくなっていると思う
12:23 PM
省略出来る箇所が増えてるなら、優しくなってそうですね
12:24 PM
うーん、とすると、Combine使うなら最初にこれ入れておきたいレベルで便利だな
Avatar
普段のflatMapは -> AnyPublisher<> がほぼ必須だけど、resultBuilder経由してると今の所書かなくて済んでる
Avatar
flatMapがanyPublisher無しだと誰も書けません!w から、思考停止で書ける、まで昇華される
12:26 PM
実行時にどれくらいパフォーマンス稼いでくれるのかは気になるね。
12:26 PM
anyPublisher使ったらその時点でPWTの参照入るけど
12:26 PM
ResultBuilderならPWT無しでいけるんじゃないか
Avatar
PWTは何の略ですか
Avatar
Protocol Witness Table
12:27 PM
この場合はsubscribeの動的ディスパッチになるか、ならないかを指してます
Avatar
AnyPublisherでラップしないから軽減されてそうですね
Avatar
全部Genericsで動いていてTE無しなら、動的ディスパッチなくせる気がする
Avatar
試しに型覗いてみたら画面横幅いっぱいのウィンドウで4行くらいの型が出てきてよかった
12:33 PM
スクショ貼りたかったけどさすがに断念
Avatar
間にEitherも挟まってるから余計に長そう
12:34 PM
ところで、私のExpressiveを使うと
12:34 PM
不要なときはEitherが消えるので(殆ど無いが)
12:34 PM
ちょっとだけ短くなるかも?
Avatar
一応僕が使ってるのはこんな感じですね https://gist.github.com/sidepelican/a2045cb614c603cd2fcf6ada22cf509a
GitHub Gist: instantly share code, notes, and snippets.
12:35 PM
最小限しか書いてないけどこれで動いてたからこれでやってる
Avatar
レビューすると、FlatMapBuilderそのものは型パラ要らない気がする
12:36 PM
ResultBuilderの型パラは、結果から型を縛る(?)というテクい事をするときしか役に立たなくて、基本は無くてもよしなに推論してくれるようになってる (edited)
Avatar
ほんとだ。なくてもビルド通りました (edited)
Avatar
ResultBuilderの作り方と推論の仕組み、かなりテクいので、どこかで紹介したいですね
12:40 PM
アーーーーOptionalの記事書いてないわ、詐欺師じゃん
Avatar
Kishikawa Katsumi 4/13/2021 6:30 PM
https://github.com/apple/swift/commit/c76dac715552082178a390bf9472b444af628296
We don't want @asyncHandler to be part of the concurrency model, so put it behind a different flag.
なんか@asyncHandler-enable-experimental-async-handler つけないと使えなくなってる。
(edited)
We don't want @asyncHandler to be part of the concurrency model, so put it behind a different flag.
Avatar
Kishikawa Katsumi 4/13/2021 7:21 PM
-enable-experimental-async-handler つけてもシンボルがない、みたいなこと言われるな。
Avatar
Avatar
Iceman
一応僕が使ってるのはこんな感じですね https://gist.github.com/sidepelican/a2045cb614c603cd2fcf6ada22cf509a
flatMapのオーバーロードがいくつか足りなかったので足した
Avatar
@tarunon flatMapにresultBuilder使うやつ、型推論が劣化するケースを見つけて残念に思ってるのですがなにか解決方法思いつきますか?
Avatar
外からFailureを指定できないんだっけか
Avatar
func `catch`( _ handler: @escaping (Self.Failure) -> Empty<Output, Never> ) -> Publishers.Catch<Self, Empty<Output, Never>> { Publishers.Catch<Self, Empty<Output, Never>>(upstream: self, handler: handler) } 一応こういうの定義すると解決はできるんですが、できればresultBuilder側でいい感じになれたらなぁと
4:07 PM
resultBuilder側に無理やりFailure型を指定させても解決できないんですよね
Avatar
ワイちゃんの奴でやってみよ
4:07 PM
pcない!
4:08 PM
私の書いた奴はちょっと型推論のパワー上げてるので
4:08 PM
ワンチャンいけるんじゃないかと思う (edited)
Avatar
おお。今日はもう眠いので寝ちゃいますが吉報を待っています
Avatar
とおってなかったわw (edited)
4:16 PM
私の奴、ちょっと悪いことしてオーバーロードしてるから純正flatMapが通っただけでした
Avatar
解ったのは、ResultBuilderなクロージャの中ではさらにネストしたクロージャへの型推論が弱いかもしれないってことですね
Avatar
ネスト関係なくダメっぽいんですよね。外の型に内側の型をあわせる働きがなさそう
Avatar
それは私のは通った
Avatar
まじか〜〜
Avatar
あー、ちょっと違うかも知らん
3:30 AM
昨日似たことやって通ってたので、後でやってみる
Avatar
Hi everyone. The review of SE-0309, "Unlock existentials for all protocols", begins now and runs through May 1, 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 revie...
Avatar
existentialは何でも作れるようにするやつ
11:24 PM
審査始まった
11:24 PM
ラトナーが3で賛成しててついでにany P構文への移行計画を話してる
Avatar
any P アツい
Avatar
おお、 any 期待。
Avatar
ディスカッションも大勢はany P welcomeな論調っぽい。Errorのようなself conformingへの言及もありますね
Avatar
@swift-5.3.3 func take(_ c: () -> Optional<Int>) {} take { Optional(nil).map { v in return v } } take { Optional(nil).map { v in _ = 0 return v } }
Avatar
exit status: 1 with stderr:<stdin>:10:25: error: unable to infer type of a closure parameter 'v' in the current context Optional(nil).map { v in ^
Avatar
これ何でだめなんですっけ
Avatar
omochimetaru 4/20/2021 3:14 AM
Optional(nil) の型を決めるためにはクロージャの中身が v をそのまま転送しているだけであるって事を考慮しないといけないけど
3:14 AM
2文以上のクロージャの中身は
3:14 AM
クロージャ自体の推論が終わった後に中の推論をするから。
Avatar
なるほど。前者が特殊で、1文だけだったら中身まで見てよりリッチに推論しているということでしょうか?
Avatar
omochimetaru 4/20/2021 3:17 AM
そう。1文のクロージャのときは、クロージャの外側と中身から作れる制約式を全部一気に推論機に突っ込む。
Avatar
なるほど〜〜〜〜ありがとうございます!
🙂 1
Avatar
ResultBuilderを挟むと推論が通る気がする
Avatar
Avatar
tarunon
ResultBuilderを挟むと推論が通る気がする
omochimetaru 4/20/2021 3:35 AM
yes。ResultBuilderはその制限を外す。
Avatar
変数宣言が使えるようになったお陰で、こういうシチュエーションもハマるようになったね、
Avatar
omochimetaru 4/20/2021 3:36 AM
たしかに。
3:37 AM
2文クロージャの推論の分割は、コードをわかりやすくするためと、推論時間の増加を防ぐための2つの理由が書かれているんだけど
3:38 AM
ResultBuilderは推論時間の増加を防いでそういう推論が上手いことできる仕組みを導入したので、 もう2文クロージャの制限を外してもいいんじゃない?って意見に対してドーグがそれもそうかもみたいな事を言ってたのを見た。
Avatar
ResultBuilderの中で kawa.map { ~~~ } してるときに推論が正しくできなくてこれに遭遇したんですよね
Avatar
omochimetaru 4/20/2021 3:38 AM
ResultBuilder書いてる時頭がリミッター解除モードになってるからつまづいたのかw (edited)
Avatar
変数宣言できるようになったけどその場合にreturnする値はどう決めるのがいいんでしょうかね?最後の式をreturnなしで返すのが一番違和感ないのだろうか
Avatar
omochimetaru 4/20/2021 3:40 AM
ResultBuilderに関しては式が3つあるなら3つとも渡るでしょ?
Avatar
let宣言は返り値として採用されず
Avatar
omochimetaru 4/20/2021 3:41 AM
View { Text() Text() Text() } みたいな。
Avatar
最後の一文が返り値として採用される
Avatar
omochimetaru 4/20/2021 3:41 AM
あれ、そうなん
Avatar
まあ解りやすくするためにreturn書いてもok
Avatar
あ、そうなんですけど、その3つの式を合体させたくないケースにおいてどうするのが正解なのかなと
3:41 AM
returnかけなくないですか?
Avatar
omochimetaru 4/20/2021 3:42 AM
returnは書けないんじゃないっけ。
Avatar
return 書いた時点で result builder 扱いじゃなくなります。
Avatar
あ、書けないのか
Avatar
Avatar
rintaro
return 書いた時点で result builder 扱いじゃなくなります。
omochimetaru 4/20/2021 3:42 AM
「扱いじゃなくなる」という挙動があるのか〜!
Avatar
書けるけど、その場合は普通のクロージャとして扱われる。
Avatar
Avatar
Iceman
returnかけなくないですか?
omochimetaru 4/20/2021 3:42 AM
_ = Text() こうすれば消せるんじゃない?
Avatar
兎に角、式を返り値として採用したくないなら、let foo = myMethod() みたいにして
Avatar
それはVoidがかえるんですよ
Avatar
消してしまえばokと思う
Avatar
omochimetaru 4/20/2021 3:43 AM
じゃあ let _ = Text()  ・・・
Avatar
letにVoidを吸わせれば帰らない
Avatar
letに吸わせると返らないの知らなかった・・・
3:44 AM
ありがとうございます
Avatar
ちなみに複数文クロージャの型推論実装 https://github.com/apple/swift/pull/32223
Avatar
ウオオ
Avatar
Avatar
rintaro
ちなみに複数文クロージャの型推論実装 https://github.com/apple/swift/pull/32223
omochimetaru 4/20/2021 3:44 AM
main ブランチ対応で自動closeされてるwww
Avatar
1年前じゃん
Avatar
omochimetaru 4/20/2021 3:44 AM
そうそう、このPRを見た記憶があったんですよ。一応完成してたんですね。
Avatar
あ、自動closeされてそれっきりなんですかこれ
Avatar
omochimetaru 4/20/2021 3:45 AM
俺が知る限りは動きはない
3:46 AM
_ = aVoid 扱いになるのはこれとは別なのかな
Avatar
_ = って書けるの知らなかったんだけど
Avatar
omochimetaru 4/20/2021 3:48 AM
うおーいけたー
3:48 AM
代入文は式として使えないんだと思いこんでいた
3:48 AM
代入文おまえ式だったのか
Avatar
むしろ_ =let _ = と同じだと考えてしまっていた
Avatar
omochimetaru 4/20/2021 3:49 AM
3:49 AM
let文は式ではなかった。
Avatar
それはそうだね
Avatar
Avatar
Iceman
むしろ_ =let _ = と同じだと考えてしまっていた
omochimetaru 4/20/2021 3:49 AM
俺もそう考えてた。let の略記なのかと思ってた。
Avatar
Avatar
Iceman
むしろ_ =let _ = と同じだと考えてしまっていた
そうじゃなかったのか・・・。
Avatar
letの略は出来たらダメでしょw
Avatar
omochimetaru 4/20/2021 3:50 AM
3:50 AM
左辺に変数があってもオッケー。 (edited)
Avatar
それなら Void になるのも自然な話だ。
Avatar
これ出来るからと言ってResultBuilderで副作用のある関数をほいほい呼ぶのは
Avatar
あれ?でも = は関数じゃないのか。
Avatar
期待した副作用と異なる結果になる事があるのでよろしくない
Avatar
omochimetaru 4/20/2021 3:51 AM
同意。
Avatar
@swift-5.3.3 var x: Int? = nil (x? = 12).map { _ in print("assinged")} ?? print("was nil")
Avatar
was nil
Avatar
omochimetaru 4/20/2021 3:53 AM
ただ多くの言語だと代入文の型はVoidじゃなくて右辺の型なんだけどな〜
Avatar
確かにそうね
3:53 AM
それでもって a = b = 2 みたいなの書くことがある
Avatar
omochimetaru 4/20/2021 3:54 AM
それを利用して a = b = 3 みたいに かぶった
Avatar
assign を void にしたのは何かしら rationale があった気がする
Avatar
if の条件中で代入を許さずみたいなのじゃなかったですっけ?
Avatar
それか
Avatar
omochimetaru 4/20/2021 3:55 AM
それならそもそも式にしなければよいのでは
Avatar
= は代入文じゃなくて binary expression の一部として式だった。
Avatar
omochimetaru 4/20/2021 3:56 AM
あーoperatorが定義されているのか
Avatar
頭にキーワードが無いと普通の binary expression と区別がつかないので、式にしないと Parser 実装が面倒くさくなるのはありますね。
3:57 AM
= オペレータの定義はないはずです。
Avatar
omochimetaru 4/20/2021 3:57 AM
あーそうか、代入文よりも優先度の低い演算子を作れるようにするためにはそれしか無さそう
Avatar
@swift-5.3.3 var a: Void = () var b: Void = () a = b = a = b = a
Avatar
no output
3:58 AM
たしかになかった。
Avatar
Swift でも a = b = a = b = a みたいなのが書けるケースがあるとは。
Avatar
omochimetaru 4/20/2021 3:58 AM
*= とか はあったけど。
Avatar
Avatar
koher
Swift でも a = b = a = b = a みたいなのが書けるケースがあるとは。
omochimetaru 4/20/2021 3:59 AM
めっちゃ虚無の式だ・・・
3:59 AM
// User-defined assignment operators are not supported. The = operator is // hardcoded as if it had the following attributes: // infix operator =: AssignmentPrecedence
3:59 AM
↑コメントアウトされてた。
Avatar
Avatar
omochimetaru
めっちゃ虚無の式だ・・・
取り扱ってる値が虚無( Void )な上に何も変更しないので虚無。
👻 1
Avatar
Calling these “skipping stone statements” try = = = = = = { “splash” }()
Avatar
omochimetaru 4/20/2021 4:30 AM
ww
4:30 AM
Avatar
Xcode12.5から自作resultBuilderで作ったスコープの{} の色が変わるようになったw
Avatar
omochimetaru 4/27/2021 8:47 AM
おお、便利そう
8:48 AM
resultBuilder適用部分とそうでない部分が区別できる
Avatar
ifと同じ色になってるのか、あーこれはifがrbの影響になるから (edited)
Avatar
omochimetaru 4/27/2021 8:48 AM
ifもRBに畳まれてるからじゃない?
Avatar
理解
Avatar
omochimetaru 4/27/2021 8:49 AM
これはいいな 魔術モードなのがわかるので
Avatar
影響がある部分のハイライトもされる
Avatar
よくできてんな
Avatar
omochimetaru 4/29/2021 5:42 PM
Hello, Swift community. The review of SE-0312: Add indexed() and Collection conformances for enumerated() and zip(::) begins now and runs through May 7th, 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 t...
5:42 PM
@koher が最近、標準に欲しいと言っていたやつ、標準化する審査入りました↑
Avatar
皆のコメントが雑に +1 だけで笑う
Avatar
omochimetaru 4/29/2021 5:47 PM
Motivationに書いてあるこれがほんとそう
For many collections this integer offset is different from the Index type, and in the case of ArraySlice in particular this offset is a common source of bugs when the slice’s startIndex isn’t 0.
Avatar
0始まりじゃないindexで混乱するといえばsql
5:48 PM
しかも丁寧に0じゃないよってエラーで言ってくる
Avatar
おお、素晴らしい!
Avatar
@stzn3 そのほうがわかりやすくていいね
Avatar
spawn だと await するのとの関係がわかりづらくないかな?
12:01 PM
どういう議論があったのかは追えてないけど。
Avatar
async let だと並行処理になるって事がわからないんで
12:01 PM
知らなきゃそこが並行であることは全く予想できないと思うんですけど
12:01 PM
spawn letだったら初見でも想像できそう
Avatar
そうかなぁ。 await する箇所で suspend するってだけで十分なわかる気がするけど。
Avatar
型名のPに二つの意味があってわかりにくいからany Pになったように
Avatar
suspension point は await なんだから、 async let で suspend せず並行に実行されるのは推測可能だと思う。し、 spawn だから初見でも推測できるというのは微妙かと。 (edited)
Avatar
別の意味のasyncが2つあるのは混乱しそう
Avatar
この場合は await と結びついてるから自然じゃない?
12:04 PM
むしろ、 async がないのに await しなきゃいけないのが混乱しそう。 (edited)
12:06 PM
↓とかでもよかったのかもしれないなぁ。 let a: async Int = foo()
Avatar
この記法だと解りやすいけど型を明示する必要があってしんどいですね 型を_で略記できる仕様があればこれになったかもしれない
Avatar
たしかに。推論させる場合は↓とかかなぁ。 let a: async = foo()
5:05 PM
() async -> Intasync が型であるように、 spawn let とかも型であるのが自然な気がする。
5:06 PM
まあ、 async IntPromise<Int> みたいなものなんだけど。
Avatar
child taskを生成するのでspawnを共通で使用する、というのが主な理由ですかね👀 We feel that using the word spawn in every case that involves the creation of a child-task is simple to understand and allows developers to learn and assume about both features in tandem. https://github.com/apple/swift-evolution/blob/5a9aaec2f95a14dd8ad6db64e6278e2a83a9b8d4/proposals/mmmm-spawn-let.md#alternative-name-async-let (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
👀 1
Avatar
そもそも throws -> Intasync -> Int じゃなく -> throws Int-> async Int として型扱いにするのが良かったんじゃないかなぁ。そうすれば let a: async Int はすごく自然だったし、 await しないまま持ち運ぶのも自然だった。
6:26 AM
async property とかとも整合しないかな・・・。
Avatar
Avatar
koher
suspension point は await なんだから、 async let で suspend せず並行に実行されるのは推測可能だと思う。し、 spawn だから初見でも推測できるというのは微妙かと。 (edited)
omochimetaru 5/1/2021 6:27 AM
awaitがsuspension pointを示すのは、非同期である事は示しているけど、並行である事は示さないです。 async/awaitはあくまで直列な処理の構文なので。
6:29 AM
spawnという言葉から推測できるというのは、Structured Concurrency API の方で spawn メソッドがあるから、という話とセットですね。
6:29 AM
実際spawnメソッドをメソッド呼び出しじゃなくて言語構文として書ける機能だし。
Avatar
async let a = foo() async let b = bar() let c = await a + b としたときに、 foobar の中の suspension point に至るまでもなく並行に実行されるからか。
6:31 AM
たしかに async とは概念が違う気がする。
6:32 AM
うーんでも async IntPromise<Int> 的な扱いにして整理するのはありだったと思うけどな。
6:32 AM
一般的なモナドと違って合成がしやすいものとして。
Avatar
omochimetaru 5/1/2021 6:35 AM
型扱いにした場合、
6:35 AM
let a: async Int = foo() みたいに書く事になるけど、
6:35 AM
foo() の返り値の型 Int が async Int 型に暗黙昇格するのはまあいいとしても、
6:36 AM
それが、foo() から値が返った 型変換のタイミングではなくて、 fooの呼び出しそのものを 並行に投げる事になるのは、
6:36 AM
他の言語機能と比較すると唐突な挙動に感じます
6:37 AM
async let だと、 let の初期化代入文そのものにかかってるmodifierになるので、
6:38 AM
右辺値の処理に特別な変更があるのはまあ構文構造的には妥当に見える。
6:38 AM
let a = spawn foo() 構造的な観点で、「並行に投げる」作用を記述する点で言えば↑これでも良さそうな気がするけど・・・ (edited)
6:39 AM
右辺値の処理を並行に投げるだけじゃなくて、左辺値の「変数aをこのスコープの中でawaitせねばならない」っていう (edited)
6:39 AM
特別な静的な制約も導入しているという意味では
6:40 AM
let文自体の属性になっているのがやっぱり一番妥当に思います (edited)
Avatar
よく考えてみたら、これできないのは当たり前と言えば当たり前ですが…どうしてもこれやりたい時、TypeErasure以外で何か方法はありますか? protocol TestObject: AnyObject { associatedtype Some func doSomething<Item>(with item: Item) -> Some } final class Test: TestObject { func doSomething<Item: View>(with item: Item) -> Optional<Item> { return item } } ちなみに何をやりたいかというと、SwiftUIのViewを渡して、それを内包するコンテナViewを返して欲しいわけです
Avatar
Higher Kinded Typeが必要(エスパー)
Avatar
つまり現段階のSwiftではやはり無理ですね… 😇
Avatar
associatedtypeを指定せずに protocol TestObject: AnyObject { func doSomething<Item>(with item: Item) -> Optional<Item> } はダメなんですかね
7:22 AM
associatedtype無しなら可能
Avatar
まあ可能ですね、ただしジェネリクスが多用しすぎて相当カオスな型になっちゃっていますw
Avatar
どちらかというとprotocolを使った問題解決よりは、関数とoverload, ORTあたりを使った解決を目指すと
7:24 AM
解に近づく予感がします
Avatar
とりあえず <Item> のジェネリクスを外して対応します
Avatar
Avatar
omochimetaru
それが、foo() から値が返った 型変換のタイミングではなくて、 fooの呼び出しそのものを 並行に投げる事になるのは、
これ GW で返事し忘れてた。どうして Promise<Int> ならよくて async Int 型だと不自然に感じるのか考えたんだけど、 Promise だとイニシャライザに明示的にクロージャ式で生成してる感があるからなのかな。クロージャ式に渡した部分が並行に実行されても違和感はない。 でも、 withUnsafeContinuation とかだとクロージャ式で渡すのは同じだし、 JS でもたとえば const a = asyncFoo(); const b = asyncBar(); const sum = await a + await b;asyncFoo/Bar の戻り値が Promise のコンストラクタで生成されたとは限らない( await の結果かもしれない)し、慣れの問題な気がする。 async Int が扱いやすいかは別として、 async IntPromise<Int> に本質的な違いはないんじゃないかな。
Avatar
モナドかどうかぐらいの差だと思います
3:40 AM
それでいうと、spawn letは事実上のPromise<Int>だがモナド表記を避けているだけと言える
3:40 AM
逆にPromise(Future)モナドが最初からあれば、spawn letはそっちに丸め込まれたかな〜とかは思いますね
Avatar
omochimetaru 5/10/2021 3:41 AM
@koher @tarunon いやいや、型は型でしかないけど、 spawn letにはスコープに束縛された実行を終了待機するという実行制御も含まれているので、 型の機能を超えているので型としてみなすのはおかしいと思います。 (edited)
Avatar
あーーawaitしないとコンパイルエラーになるのか
Avatar
omochimetaru 5/10/2021 3:41 AM
関係性としては、Promise型を含んでいるけど、さらに広範囲な機能です。
Avatar
その機能は把握できてなかった。偉いね。
👌 1
Avatar
omochimetaru 5/10/2021 3:42 AM
なのでlet文に対するアノテーションなのが妥当だというのが僕が↑でかいた意見です。
Avatar
機能的にはPromiseにコンパイルチェックが乗算された格好なのか。いいね
Avatar
omochimetaru 5/10/2021 3:42 AM
letにはこれまでにもif-elseの両方で初期化されないといけないとか、そういう制御フロー的な機能がある。 (edited)
Avatar
yutailang0119 5/10/2021 3:45 AM
Originally part of the Structured Concurrency proposal, ripped out into it&#39;s own proposal by @jckarter many months ago :-) This is now updated to reflect present day structured concurrency...
🙃 2
Avatar
omochimetaru 5/10/2021 3:46 AM
え〜w spawnメソッドと揃えたいんじゃないんか・・・
Avatar
まあ、 async は asynchronous とは限らないけど他言語とのわかりやすさを考えて async にするみたいな話もあった気がするから、挙動として適切なネーミングよりも async 系のものは async で統一するのはわかりやすい気もする。
Avatar
omochimetaru 5/10/2021 3:48 AM
そもそもspawn letってpitch出たんだっけ。
3:50 AM
まだ文書はspawn letで、
It'll be async let after all, need to update the proposal again.
再変更に関してはこんらっどさんが書き込んだだけなのか・・・
Avatar
Avatar
omochimetaru
@koher @tarunon いやいや、型は型でしかないけど、 spawn letにはスコープに束縛された実行を終了待機するという実行制御も含まれているので、 型の機能を超えているので型としてみなすのはおかしいと思います。 (edited)
async 型は async 型のまま外に持ち出せないというルールを加えれば同じにならないかな? inout 型のように。つまり、必ず await しなければならなくなる。
Avatar
それはもうそうなってるんじゃ (edited)
Avatar
omochimetaru 5/10/2021 3:54 AM
外に持ち出せないこととawaitしなけらばならないことは別じゃないですか?
Avatar
↑書きながら思ったんだけど、 async -> Void の場合って async let はどうなるんだっけ?↓みたいにしたら暗黙的に末尾で await されるんだっけ? func f() async { async let _ = foo() async let _ = bar() }
Avatar
omochimetaru 5/10/2021 3:56 AM
inoutのように引数でしか使えない型(型modifier)のような感じで変数宣言だけでしか使えない型としてそういう制約を入れるという形なら辻褄は取れるかも?
Avatar
Avatar
tarunon
それはもうそうなってるんじゃ (edited)
async Int があった場合の話です。↓みたいなのを許さない。 func f() -> async Int { let a: async Int = foo() return a // コンパイルエラー }
Avatar
omochimetaru 5/10/2021 3:56 AM
async Int が関数返り値に書けてしまうと話が変わると思います。
Avatar
仮にそうあったとしたら、それはコンパイルエラーでいいと思います。
Avatar
Avatar
omochimetaru
inoutのように引数でしか使えない型(型modifier)のような感じで変数宣言だけでしか使えない型としてそういう制約を入れるという形なら辻褄は取れるかも?
そうだね。戻り値には書けない方が良さそう。
Avatar
関数返り値にasyncは書けないで統一でいいんじゃないだろうか。
Avatar
omochimetaru 5/10/2021 3:57 AM
任意の非同期関数 (async -> Int) に対して、スコープ束縛並行実行を完結に書けるという話なので。
Avatar
async -> Intlet a: async Int なら良さそうな気がする。
Avatar
omochimetaru 5/10/2021 3:57 AM
そうですね。
Avatar
本質的には同一なので、同じことを2通りで書けるよりは、1つに統一してしまっていいと思う
Avatar
そうすると async 引数はあってもよい? inout みたいな。
Avatar
omochimetaru 5/10/2021 3:59 AM
SEプロセス的にはStructured Concurrencyのレビュー期間がとっくに終わってるのに完了処理がされてない状態で、 spawn letの文法に関してはまだpitchも出てないのかな?
Avatar
async引数はなんか嫌な予感がするんだよな
3:59 AM
throwsと同じで、関数を引数に取るなら良さそう
Avatar
func foo(x: async Int) { ... } let a: async Int = foo() foo(x: a)
Avatar
だめだと思います
Avatar
呼び出し時に何か & の代わりがほしいけど
Avatar
omochimetaru 5/10/2021 4:00 AM
それ実質的にオーナーシップなんですよね
4:00 AM
ようするに、スコープを出るまでにawaitしないといけないかわりに
Avatar
fooがawaitしないとおかしなことになる
Avatar
omochimetaru 5/10/2021 4:00 AM
async引数にわたすことでも consume できるってことですよね
Avatar
Avatar
tarunon
fooがawaitしないとおかしなことになる
omochimetaru 5/10/2021 4:01 AM
それも強制されるとすればいけそうだね。
Avatar
Avatar
tarunon
fooがawaitしないとおかしなことになる
fooawait しないとコンパイルエラーじゃないでしょうか?
Avatar
func foo(x: async () -> Int) { ... } こうするべきだと思うよ
Avatar
omochimetaru 5/10/2021 4:01 AM
それは意味が違うんよね
Avatar
async X 型の宣言者は await する責任を負い、
Avatar
そう、その違う意味のみ許可する方法が良いと思う
Avatar
omochimetaru 5/10/2021 4:02 AM
それだとxの呼び出し時点で非同期な取得を開始する事になる
Avatar
async X 引数を持つ関数に渡すことでその責任を譲渡する。
Avatar
そうです。そこの段階で切り分けてしまったほうが、結果として全体の仕様がシンプルになると思う
Avatar
omochimetaru 5/10/2021 4:03 AM
x: Promise<Int>await x.get() でいい感はある
4:03 AM
非同期はたくさん使いたいけど、並行実行はそんなあちこちに出現しないと思うんですよね。
Avatar
throws () -> T が事実上の Result<T, Error> であるのと同様に
4:03 AM
async () -> T も事実上の Promise<T> だからね
4:04 AM
それで渡すのが丸い
Avatar
Avatar
omochimetaru
x: Promise<Int>await x.get() でいい感はある
これ言ったら async let もそもそも Promise で良いとならない?
Avatar
omochimetaru 5/10/2021 4:04 AM
スコープ一個までならやることあるんですよね。
4:05 AM
それを引き渡して更にデータフローをつなげたことはない。
Avatar
async let a = foo() async let b = bar() return await a + blet a = Promise { await foo() } let b = Promise { await bar() } return await a.get() + b.get() で済ませられる。やや面倒なだけで。
Avatar
そうした場合は、a,bのawaitをすっぽかしたときにコンパイルエラーにできないんですよね (edited)
Avatar
omochimetaru 5/10/2021 4:06 AM
いえ、下に関しては b について触らなくてもいい点が違います
Avatar
TSだと結構発生してデバッグも辛いのでしんどい
Avatar
omochimetaru 5/10/2021 4:06 AM
上はaとbがスコープに縛られている。
4:08 AM
await withTaskGroup(of: CookingStep.self) { group in group.spawn { try await .vegetables(chopVegetables()) } group.spawn { await .meat(marinateMeat()) } group.spawn { await .oven(preheatOven(temperature: 350)) } for await finishedStep in group { switch finishedStep { case .veggies(let v): veggies = v case .meat(let m): meat = m case .oven(let o): oven = o } } }
4:08 AM
↑これの、withTaskGroup のように、async letを含む関数全体が振る舞う。
Avatar
つまり、 await 強制の機能はほしいから async let はほしいけど、それを引き渡してまで階層的に処理したいことはないから async 引数はなくてもいいんじゃないか?ってこと?で、稀にそれが起こったら x: Promise<Int> で渡すので良いと。 (edited)
Avatar
omochimetaru 5/10/2021 4:09 AM
そうですね。 ↑withTaskGroupを使いたいことはあると思うので、それのsugarがあるのは助かるって感じ。
4:11 AM
withTaskGroupだと結果をreduceするところが [T] になっちゃうけど、 async letだと (A, B, C) になっててもっと便利だな。 (edited)
Avatar
引き渡したいケースが思いつかないのは同意だけど、もしやりたいケースが見つかったときに Promise 導入は微妙なので、 async 引数的なものを導入したくなることを見越すと、 inout との整合性で async let a: Int よりも let a: async Int の方が良い気がする。
4:13 AM
async 引数は現段階で導入しないにしても。
Avatar
inoutは別に書き込まなくても処理は破綻しないけど、asyncで渡すとawaitしなければ破綻するんですよね。そういう意味でいうと性質はthrowsのほうが近いので
4:19 AM
throwsと同じ扱いで基本的に良いと思うんですよ
Avatar
omochimetaru 5/10/2021 4:20 AM
引き渡しに関して言えば、 Result<T> の代わりに使える throws Int 型があっても良いという話になりますね。 (edited)
4:21 AM
Promise<T> を導入しなくて良いように、 async Int 型を導入するというアイデアなので。
Avatar
いやーーー
Avatar
omochimetaru 5/10/2021 4:21 AM
Optional<T> に対して Int? があるのと同じで
4:21 AM
型syntaxレベルの話かな。
Avatar
throwsもasyncも、スコープの中で処理を確実に完了させるための意味合いも現状あるわけで
4:21 AM
それを棄却してまで実装するのはどうかと思うんだよな
4:22 AM
optional/inoutとはわけが違う
Avatar
throws Int も必ずスコープの中で try しなければならないということになるんじゃないでしょうか。
Avatar
そもそも引数として渡した時点でerror処理がセットになるので、do try catchで書けなくてthrows関数にする or 他のthrows Int引数に渡すという結構アクロバティックなルールになるはず
4:56 AM
そういう整合性を合わせるために無理くりなルールを導入するくらいなら、現状の関数でのみ渡せて評価とハンドリングがセットになる、という仕様のほうがよいです。
4:56 AM
これと同じことが、async T引数でも発生すると思います。
Avatar
↓みたいなイメージ。 func f() { do { let a: throws Int = foo() let b: throws Int = bar() print(try a + b) } catch { print(error) } }
4:58 AM
この例の場合 throws Int にする意味はないけど。
Avatar
ああ、同一スコープ内ではOK 一方で引数に渡せるようにするのは複雑性が爆発するのでNGです
4:58 AM
fooが失敗してもbarを実行するので、直列ではなくなりますね。
Avatar
そうですね。
Avatar
omochimetaru 5/10/2021 4:58 AM
必ずtryしなければならないは今も実現できているけど、 tryする代わりに引数に渡せる ができるようになる。
4:59 AM
なんか可読性が低くなりそうだな。 inoutの& みたいにマーキングが必要そうですね。
Avatar
仮にそれを認めて整合性のあうルールが出来たとしても、それはそれで型検査が連鎖的にしんどくなると思う
Avatar
Avatar
omochimetaru
なんか可読性が低くなりそうだな。 inoutの& みたいにマーキングが必要そうですね。
& 的なのはほしい。
5:00 AM
全部 & にするんじゃなければ記号が足りなくなるなぁ。
Avatar
omochimetaru 5/10/2021 5:01 AM
記号が増えるのも嫌ですね。
Avatar
foo(throws a) とか foo(async b) とか書けばいいのかな。
5:02 AM
滅多にないパターンだから、これくらいのタイプ数は許容できそう。
5:02 AM
throws X, async X 型、結構ありだと思うけどなぁ。引数は別として。
5:03 AM
async let だと try 必要なのかわかりづらいし。
Avatar
引数と変数に許可した瞬間に複雑性が爆発するんだよな。ローカルスコープはいいんじゃないかと思うけど。
Avatar
戻り値の型には許可しないんでローカルスコープは守られますね。
Avatar
ところで、@autoclosure を使えば利用側にtry/awaitを明示する形でやりたいことが出来るんで、実際のシーンではそれでもいいかなぁという気はしますね。
10:42 AM
スコープを跨いで処理を持ち越すのはそもそもNGとして、そうではなく表記上やりたいことができればOKとする
Avatar
↓って extension Array: IntCollection {} 前提での話?? protocol IntCollection: RangeReplaceableCollection where Self.Element == Int {} let array: IntCollection = [3, 1, 4, 1, 5] array.append(9) // OK, 'Self.Element' is known to be 'Int'. https://github.com/apple/swift-evolution/blob/main/proposals/0309-unlock-existential-types-for-all-protocols.md#proposed-solution
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
そうです
11:18 PM
たしか今までは
11:18 PM
親プロトコルがassociatedtypeを持ってるプロトコルは
11:19 PM
existentialにできなかった
Avatar
いきなり ArrayIntCollection に適合してないのに IntCollection に代入できててびっくりした。
Avatar
ああ。文章の上の段の話と繋がってるという理解
Avatar
We suggest allowing any protocol to be used as a type and exercise the restriction on individual member accesses uniformly across extension members and requirements. Additionally, the adjusted access criteria for protocol members shall account for associated types with known implementations:
11:25 PM
うーん、それにしても extension Array: IntCollection {} が 2 行目にあった方がいいんじゃないかな?
Avatar
PR出して良さそう
Avatar
‼️ https://forums.swift.org/t/improving-the-ui-of-generics/22814/162
Yes, I'm working on an implementation of general opaque result types, i.e. func foo() -> <T> T where T.U == Int.
Yes, I'm working on an implementation of general opaque result types, i.e. func foo() -> T where T.U == Int.
🤩 2
😮 1
Avatar
omochimetaru 6/3/2021 2:18 AM
https://github.com/search?q=bdriscoll&type=users うーんGitHubには居ない?コントリビューターかどうか調べようとしたんだけど。 (edited)
2:20 AM
他に投稿もないな、何者なんだろう・・・
Avatar
Computer science and math student at UC Berkeley. willtunnels has 12 repositories available. Follow their code on GitHub.
2:20 AM
この人かな
Avatar
omochimetaru 6/3/2021 2:21 AM
あ、このランダムアイコンって連携してるんだ
2:21 AM
@apple
2:21 AM
In order to support generalized opaque return types like func foo() -&gt; &lt;T&gt; T where T.U == Int, we need this syntax extension. See https://forums.swift.org/t/improving-the-ui-of...
2:22 AM
ほんとだ。パーサーから着手してる。
Avatar
General Opaque Type というか Reverse Generics ?
Avatar
omochimetaru 6/3/2021 3:09 AM
i.e. func foo() -> <T> T where T.U == Int
と本人が投稿しているのでそうだと思います。
3:10 AM
Opaque Result Type の一般化構文だからgeneral opaque typeと個人的に呼んだんじゃないだろうか。
Avatar
これが来るとすごくうれしいですね。
3:25 AM
some Sequence<.Element == Int> とかが先に来るかとも思ったけど、これは Generalized Existential との構文の兼ね合いがあるから後回しなのかな?
Avatar
omochimetaru 6/3/2021 3:36 AM
パラメータ付きのopaque type(some keyword)を作るのと、reverse genericsを作るのって、ABI的には同じタスクじゃないだろうか?
3:37 AM
てか、opaque typeも、ABI境界をまたいだ状況だと具体型が消去されて抽象化されるので、generalized existentialのベースになる?
Avatar
↑これ思いました
Avatar
omochimetaru 6/3/2021 3:38 AM
generalized existentialは、それに加えてユーザ側での型の扱いがあるので、その次の段階になりそう。
Avatar
existentialはスコープ外の変数格納まで含めた話なので (edited)
Avatar
ABI的には大きな変更はなくて上のレイヤーだけで解決できるのかな
Avatar
そのスコープだけで取り扱われる分、関数返り値のortの方が狭い範囲の議論になると思う
3:40 AM
あとはそも本質的にはgenericsだから複数の関数があるときに同一の型にならない
3:41 AM
existentialとはここが違う
Avatar
Avatar
Yuta Saito
ABI的には大きな変更はなくて上のレイヤーだけで解決できるのかな
omochimetaru 6/3/2021 3:41 AM
some typeとany typeの違いはコンパイル時のタイプチェックだけで実行時は同じ抽象表現に乗る気がしている。
👀 1
Avatar
あー、いや、現状のORTとReverse Genericsは同じ抽象に乗るけどany typeは別じゃないですかね
Avatar
omochimetaru 6/3/2021 3:44 AM
どこが違うかな。
Avatar
関数の返り値として使われるとき、ORTの場合返り値の型が関数の実行前に分かったり、一度calleeから実体の型を取得したらその後変わらなかったり、any typeよりもかなり狭いので同じ抽象に乗せると最適化チャンスが減って嬉しくない
Avatar
omochimetaru 6/3/2021 3:49 AM
同一型である事がわかる場合の最適化はコンパイル時のspecializeと同じで抽象化を捨てる最適化だから関係なくない?
Avatar
それができるのはcalleeのソースがモジュール内にある場合だけですよね
Avatar
omochimetaru 6/3/2021 3:51 AM
うん。
Avatar
あー、関数の実行前、っていいうのはコンパイル時というわけではなくて、
3:52 AM
call 命令の前という話です
Avatar
omochimetaru 6/3/2021 3:57 AM
そういえば前調べた内容だと
3:58 AM
some typeが返り値で変えるときの表現は、
3:59 AM
その真の型のmetatypeを返す補助関数をまず呼び出して、 その結果を使ってスタックに真の型のストレージを確保して、 callerがそのストレージへのポインタを渡して、calleeがそこに書き込むって作りだったから
4:00 AM
その時点で常に24+ byteなcontainerにラップするexistentialとは表現が違うな。
Avatar
そうですそうです
4:00 AM
たとえば、 func makeSequence() some Sequence<.Element = Int> { ... } var s = makeSequence() for item in s { print(item) } s = makeSequence() for item in s { print(item) } (edited)
4:00 AM
だと makeSequence の実体型を取得するのは理論上一回で済むですけど、
4:01 AM
func makeSequence() any Sequence<.Element = Int> { ... } var s = makeSequence() s = makeSequence()
4:02 AM
anyだとそれぞれboxから取り出さないといけない
Avatar
omochimetaru 6/3/2021 4:02 AM
ジェネリックパラメータ型の表現として真の型へのポインタを渡すという点では普通のジェネリクスと同じだなあ。 caller側が決めるジェネリクスだとmetatypeを引数で渡すけど、 callee側が決めるジェネリクスだと、それに対してmetatypeを返す補助関数を一つ用意するだけになっていて、ほかは同じか。
Avatar
そうですね
Avatar
omochimetaru 6/3/2021 4:04 AM
あー,同じ関数に対するcallのたびに変わるかどうかがあるのか。 (edited)
Avatar
渡すジェネリックパラーメータが常に同じ、に対応しそう
Avatar
omochimetaru 6/3/2021 4:08 AM
制約付きのsome typeの表現は・・・
4:08 AM
some Sequence<.Element = Int> とか、 .Element = Int は、結局 普通のジェネリクスの where で 修飾してるのと同じで、
4:09 AM
それ自体の受け渡し方やmetatypeをcalleeから取る補助関数の仕組みは変わらなそうだな。
4:10 AM
メタタイプからSequenceのwitness tableを取り出してそれ経由で操作するのは同じで、
4:10 AM
その時に、埋まってないassociatedtypeが絡む部分についてはメソッドが呼び出せないって制限についてはコンパイル時に事前にかけるだけか。
4:11 AM
そのへんの仕組みはこの前実装されてたexistentialの制限緩和と関連するな。
Avatar
existentialの制限緩和
これなんでしたっけ?
4:12 AM
これまでは、呼び出せないエントリがwitness tableに発生する状況ではそもそもexistentialとして利用することができなかった
Avatar
あー、これか
Avatar
omochimetaru 6/3/2021 4:13 AM
この機能が入ったことで、どんなプロトコルでもexistentialとして使えるようになったけど、もともと駄目だったようなassociated typeが絡むメソッドは使えない。
4:14 AM
で、associated typeが埋まってないメソッドは呼び出せないって話は、 some typeでパラメータが埋まってないメソッドは呼び出せないのと同じルールになると思った。
Avatar
Calleeから決定される型が入力に来るようなパターンですよね
Avatar
omochimetaru 6/3/2021 4:16 AM
func makeSequence() -> some Sequence<.Element = Int> { ... } この .Element についての話だから、calleeだな。
4:16 AM
Sequenceに関して言うと↑だと .Iterator が決まってないので
4:16 AM
このままだと 結局 for-in が使えない事になっちゃうので、
Avatar
for inは使えるんじゃないですか?
Avatar
omochimetaru 6/3/2021 4:17 AM
.Iterator が決まってないのであれば、 makeIteratorは func makeIterator() -> some Iterator だとみなす新しい仕組みがいるのかな。
4:17 AM
あいや、metatypeがあるから使えるのか?
Avatar
IteratorはIteratorProtocolに準拠していることがSequence側で制約かかってるので、Element = Intがない場合、どんなElementがくるかわからんけど取り敢えず回せる事になりそう
4:18 AM
@swift-5.4.3 func makeSequence() -> some Sequence { return Array<Int>([1, 2, 3]) } for element in makeSequence() { print(element) }
Avatar
swift54 BOT 6/3/2021 4:18 AM
1 2 3
Avatar
omochimetaru 6/3/2021 4:18 AM
let collection: RangeReplaceableCollection = [1, 2, 3] // error: member 'append' cannot be used on value of protocol type 'RangeReplaceableCollection' // because it references associated type 'Element' in contravariant position; use a conformance // constraint instead. collection.append(4)
4:19 AM
そうか、問題が起きるのはcontravariant positionのときか?
Avatar
入力に来るパターン
Avatar
omochimetaru 6/3/2021 4:19 AM
makeIterator() -> Iterator は covariant positionだからoK
4:19 AM
Calleeから決定される型が入力に来るようなパターンですよね
入力ってvariance的な話か。そうですね。
Avatar
varianceってワードがぱっと出てこなかったw
Avatar
omochimetaru 6/3/2021 4:20 AM
型推論機に対する条件入力とかそっちの意味かと思った。
4:21 AM
varianceというワードが出てこなくても概念が出てきているので本質的な理解度が高そう。
Avatar
「引数にassoctypeを取るクロージャ」を引数に取るようなメソッドは呼び出せるんですよね多分
Avatar
omochimetaru 6/3/2021 4:27 AM
contraのcontraはcovなのでそうですね。 (edited)
4:28 AM
あれ?ほんとか?
4:28 AM
Swiftの関数型はジェネリックパラメータを取れないから駄目?
Avatar
Avatar
Yuta Saito
「引数にassoctypeを取るクロージャ」を引数に取るようなメソッドは呼び出せるんですよね多分
これはmapとかforEachを想定してました
Avatar
omochimetaru 6/3/2021 4:29 AM
func RangereplaceableCollection.forEach(_ f: (Element) -> Void)
4:30 AM
あーいけるか。
4:31 AM
ユーザが書けないだけでクロージャが内部表現的にジェネリックパラメータを取る事はあるので
Avatar
いけそう
Avatar
omochimetaru 6/3/2021 4:33 AM
Elementだとなにもないけどプロトコルついてても同じだな。
4:33 AM
where付きの高階関数にクロージャを渡す時にユーザはそのクロージャが受け取った T: P に対してPのメソッドを呼んだりできるので。 (edited)
Avatar
これ初めてSwift触る人に説明できる自信ない…
Avatar
omochimetaru 6/3/2021 4:36 AM
どれ?
Avatar
ORTで取り出したインスタンスに対してジェネリックパラメータが絡んだメソッド呼び出しが可能なパターン
Avatar
omochimetaru 6/3/2021 4:39 AM
MutableCollectionを例に出せば直感的には理解できると思う。 func coll() -> some MutableCollection { ... } var a = coll() a[a.startIndex] = 1 // だめ。aのElementがIntかどうかはわからない a.forEach { (x) in // OK。x: Elementがなんでもいいので print(x) }
4:40 AM
↑ところでここの x に対して型を書く記法が無いっすね。
4:40 AM
func coll() -> some MutableCollection { ... } var a = coll() a[a.startIndex] = 1 // だめ。aのElementがIntかどうかはわからない a.forEach { (x: #type(of: a).Element) in // OK。x: Elementがなんでもいいので print(x) } ↑無理やり考えるならこうか (edited)
4:41 AM
#_returnType(of: coll) って実在してたっけ。
Avatar
そう、型をexplicitlyに書く記法が無いのが混乱させそう。Xcodeはこうだし…
Avatar
omochimetaru 6/3/2021 4:42 AM
そもそも some Sequence は今は無理でしょ?
Avatar
いけますよ
Avatar
omochimetaru 6/3/2021 4:42 AM
あれ?そうだっけ
4:42 AM
あそうか
Avatar
制約書けないだけで (edited)
Avatar
omochimetaru 6/3/2021 4:42 AM
パラメータを与えられないのであって、なにもないのはいいのか
Avatar
Avatar
omochimetaru
#_returnType(of: coll) って実在してたっけ。
SILレベルだとありそう
4:43 AM
これだ @_opaqueReturnTypeOf("$s24OpaqueReturnTypeExporter07exportsaB0QryF", 0) opaque
Avatar
omochimetaru 6/3/2021 4:44 AM
4:44 AM
それそれ。
4:44 AM
今書く方法ないのウケるな。
4:45 AM
_opaqueReturnTypeOf の 第二引数の 0 って、reverse generics になってcalleeが決める型パラメータが複数になったときに
4:45 AM
1, 2, 3... と index になるように用意されてる?
Avatar
ざっとテストケース眺めた感じだと今の所全部第2引数は0っぽい
Avatar
omochimetaru 6/3/2021 4:46 AM
俺も0しか見たことないんよね
4:47 AM
func foo() -> some Sequencefunc foo() -> <S> S where S: Sequence> だから、今は -> <ここ> は1要素のことしかない?
Avatar
こういうののためとか? func makeSequence() -> (some Sequence, some Sequence) { return (Array<Int>([1, 2, 3]), 0..<10) }
Avatar
omochimetaru 6/3/2021 4:49 AM
そうそう。
Avatar
これは現状書けない
Avatar
omochimetaru 6/3/2021 4:49 AM
まあ、そのケースは、一個の <T = タプル> にできる。
4:50 AM
それ言うと全部そうか?
4:50 AM
func foo() -> <T, U> (T, U) { ... }
4:53 AM
全部そうっぽい、じゃあそのsome, someのときは 1が出てきそう
Avatar
omochimetaru 6/5/2021 4:55 AM
SE-0259のpolyfillジェネレータできた。
Avatar
omochimetaru 6/5/2021 8:51 AM
You can generate Swift source code of enum with associated values which complies with SE-0295. - omochi/SE0295Polyfill
Avatar
Kishikawa Katsumi 6/5/2021 9:09 AM
enable-experimental-async-handler のフラグなくなってるな。
9:09 AM
async/awaitの話。
Avatar
Kishikawa Katsumi 6/5/2021 5:04 PM
https://github.com/apple/swift/pull/37415 asyncHandler完全になくなった。
the problem of creating a sync->async bridge
ってことだけどよくわからない。
Avatar
John McCallさんが以前こんなコメント残してましたね👀 There are a lot of basic questions about @asyncHandler that we're not confident about right now:
  • The spelling doesn't seem great.
  • Async handlers make it really easy to accidentally break structured concurrency, since the handler task is detached. Perhaps the tasks shouldn't be fully detached and need some other form of structure.
  • Async handlers currently detach immediately, which is nice for certain use cases; however, the goal was originally to support the needs of synchronous UI handlers, which almost certainly want to do an initial segment of their work synchronously.
  • Relatedly, actor-isolated async handlers become non-actor-isolated externally, which doesn't really mesh with even allowing the preferred semantics for synchronous UI handlers. https://forums.swift.org/t/new-concurrency-api-not-available-in-latest-toolchain/47389/13
(edited)
There are a lot of basic questions about @asyncHandler that we're not confident about right now: The spelling doesn't seem great. Async handlers make it really easy to accidentally break structured concurrency, since the handler task is detached. Perhaps the tasks shouldn't be fully detached and need some other form of structure. Async handle...
Avatar
omochimetaru 6/6/2021 1:33 AM
なるほど
Avatar
Kishikawa Katsumi 6/6/2021 2:06 PM
難しいな。読んだけど
Async handlers make it really easy to accidentally break structured concurrency, since the handler task is detached. Perhaps the tasks shouldn't be fully detached and need some other form of structure. Async handlers currently detach immediately, which is nice for certain use cases; however, the goal was originally to support the needs of synchronous UI handlers, which almost certainly want to do an initial segment of their work synchronously. Relatedly, actor-isolated async handlers become non-actor-isolated externally, which doesn't really mesh with even allowing the preferred semantics for synchronous UI handlers.
最初の命名以外はよくわからなかった。
2:06 PM
デタッチされるのはなんでダメなんだろう。
Avatar
omochimetaru 6/6/2021 4:01 PM
accidentally break structured concurrency なので
4:01 PM
structured concurrency は、並列に走らせたサブタスク達の完了を根本で非同期に待機する仕組みだけど
4:02 PM
そのタスクの中で何らかのAPIを呼んで、それがデリゲートメソッドを呼び戻して、そこがasynchandlerだと、
4:02 PM
detachしているので、大本の待機の仕組みからはぐれてしまうというケースの事じゃないでしょうか
4:03 PM
その次のinitial segment of their work synchronously の話は
4:04 PM
デリゲートメソッドが呼ばれて、非同期タスクを開始するにしても、その開始するまでの処理は同期になる、それが必要な状況があるのに、
4:04 PM
asyncHandlerだと全体がいきなりdetachedな非同期タスクになるから、冒頭の同期部分の処理が書けないって事を言っているのだと思った
4:05 PM
最後のactor isolatedな話は、detachedに専用に発火されちゃうので、asyncHandlerがどのアクターにも紐付けられないから、
4:06 PM
preferred semantics for synchronous UI handlers に適合できなくてうまくいかなそう
4:07 PM
preferred semanticsというのはおそらく、 例えばUIKitの処理は全部 MainActor でやり取りするってパターンを最終的に目指したいからじゃないかなあ
Avatar
Kishikawa Katsumi 6/6/2021 4:16 PM
最後のactor isolatedな話は、detachedに専用に発火されちゃうので、asyncHandlerがどのアクターにも紐付けられないから、 preferred semantics for synchronous UI handlers に適合できなくてうまくいかなそう preferred semanticsというのはおそらく、 例えばUIKitの処理は全部 MainActor でやり取りするってパターンを最終的に目指したいからじゃないかなあ
ここは納得しました。 確かにUIは全部 MainActor またはウィンドウごとのUI Actorsっていうのが理想だと思います。 他はなんとなくわかるけどまだ私の理解が足りてない。
Avatar
omochimetaru 6/6/2021 4:17 PM
UIKitからくるデリゲートメソッドの中で同期的に処理を終えないと、
4:18 PM
一瞬ずれた位置に出てる画面が描画されちゃったりする
👉 1
4:18 PM
UIにまつわる処理はデリゲートの中で同期的にすぐに終えて、 それとは別に非同期に遅れて発火(detach)したいタスクを投げるというのがよくある状況です
4:19 PM
asyncHandlerだと冒頭から全部detachedになってるので、そういうことができない。
4:19 PM
非同期な処理を投げるだけでいいような状況もあるので、
which is nice for certain use cases;
なのでしょう。
Avatar
delegateだけの特殊なルールじゃなくて、同期的関数の中から非同期関数をキックする一般的な仕組みって話の方が筋は良さそうに見えますね。
4:20 PM
それなら今出てる種々の議論も解決できる方法があるんでなかろうか。
Avatar
omochimetaru 6/6/2021 4:20 PM
それは今は新しくできた グローバル関数の async ってのがあるね
Avatar
んじゃあそれを使ってね、で完全に良さそう
Avatar
omochimetaru 6/6/2021 4:21 PM
待機はしないんだけどdetachedではない、 そのdetachedではないって事の意味は、アクターisolationのルールとの関係があったと思う、正確に理解してないけど
Avatar
Kishikawa Katsumi 6/6/2021 4:24 PM
将来の話を置くと、現在のところはasyncHandlerでメソッド全体じゃなくて async {} で適宜asyncなfunctionを呼ぶのが正しい、ということで合ってる?
Avatar
omochimetaru 6/6/2021 4:25 PM
多分そう考えてるんだと思いますけどちゃんと追ってないのでソースは把握してないです。
🙏🏼 1
Avatar
今は async {} -> Taskのinit detach -> Task.detach に変わってますね(だいぶ議論になってますが) https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md#unstructured-tasks-1 https://github.com/apple/swift/pull/37495 違いとしてはざっくりと
  • Taskのinit -> 呼び出し側のmeta情報やpriorityなどを引き継ぐ
  • Task.detach -> ↑を引き継がない
なんですかね https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md#context-inheritance 僕はasyncHandlerの代わりだと思ってます。 We might need to create new tasks whose lifetime is not bound to the creating task, for example in order to fire-and-forget some operation or to initiate asynchronous work from synchronous code
(edited)
The Task type has oscillated somewhat from being purely a namespace, to having instances that are used (albeit rarely), back to purely being a namespace that isn&#39;t used for all that many na...
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
Avatar
shiz
今は async {} -> Taskのinit detach -> Task.detach に変わってますね(だいぶ議論になってますが) https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md#unstructured-tasks-1 https://github.com/apple/swift/pull/37495 違いとしてはざっくりと
  • Taskのinit -> 呼び出し側のmeta情報やpriorityなどを引き継ぐ
  • Task.detach -> ↑を引き継がない
なんですかね https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md#context-inheritance 僕はasyncHandlerの代わりだと思ってます。 We might need to create new tasks whose lifetime is not bound to the creating task, for example in order to fire-and-forget some operation or to initiate asynchronous work from synchronous code
(edited)
omochimetaru 6/7/2021 2:13 AM
ありがとうございます 以下は結構大事に思います
2:13 AM
// Actor context propagation func notOnActor(_: @Sendable () async -> Void) { } actor A { func f() { notOnActor { await g() // must call g asynchronously, because it's a @Sendable closure } Task { g() // okay to call g synchronously, even though it's @Sendable } } func g() { } }
Avatar
あ、そうですね!actor-isolatedかどうかは大事な違いですね!
Avatar
Kishikawa Katsumi 6/7/2021 2:03 PM
だいたい読みました。TaskのAPIはけっこう苦労があって、いろいろ変わっているのはわかった。
Avatar
omochimetaru 6/7/2021 2:14 PM
名前がまたひっくり返ったのがすごいですね。
Avatar
Kishikawa Katsumi 6/7/2021 2:17 PM
iOSとかで実際にいろいろ使ってるんだろうなあ
Avatar
omochimetaru 6/7/2021 2:17 PM
Konradさんはswift-nioもやってるので、そっちの実験もしてそう。
2:18 PM
SSWG updates Since the last time we gave a major update on the SSWG, a lot has happened. First of all, we were very happy to welcome MongoDB and Amazon to the SSWG, represented by Kaitlin Mahar (MongoDB) Simon Pilkington (Amazon) Todd Varland (Amazon) Kaitlin, Simon and Todd officially joined on the 24th June last year. Further changes to...
2:18 PM
SSWGの定例会報告?が上がってて、
2:19 PM
委員は2年の期限があるらしくて入れ替わりがあって、 Gwynne Raskind (Vapor, first term) Tim Condon (Vapor, first term) Konrad Malawski (Apple, first term) Johannes Weiss (Apple, second term)
2:19 PM
Konradさんが新規参加してた。
Avatar
Kishikawa Katsumi 6/7/2021 2:20 PM
おお。
Avatar
omochimetaru 6/7/2021 2:21 PM
Konradさんめちゃくちゃ仕事してる気がする。
2:21 PM
Distributed Actorの実験もしてるし
2:21 PM
今季のGSoCの学生応募受け入れの窓口対応も担当ぽかったし
Avatar
Kishikawa Katsumi 6/7/2021 2:22 PM
スーパーエンジニアだ。
2:22 PM
そこに載ってるOpenAPIKit気になった。
Avatar
omochimetaru 6/7/2021 2:22 PM
OpenAPIってSwaggerのことかしら
Avatar
Kishikawa Katsumi 6/7/2021 2:22 PM
そうみたい。
Avatar
既存のコールバックapiをasync関数にラップする機能って提供されてるんでしたっけ。nodeのpromisifyみたいなの
Avatar
omochimetaru 6/8/2021 3:20 AM
xcodeのリリースノートに、マイグレーターの話があったよ
Avatar
マイグレーターだとサードのapiを使えないじゃん
Avatar
omochimetaru 6/8/2021 3:23 AM
ユーザーが変換するならwithUnsafeContinuationだね
👍 1
Avatar
これ多少ラップした関数作ったら嬉しい場面多そうだ
Avatar
omochimetaru 6/8/2021 3:25 AM
promisifyみたいな一発変換する高階関数は無いけど、多分引数の数ごとにジェネリクスで用意したら作れそう (edited)
Avatar
migratorはwithUnsafeContinuationを使うように書き換える?
Avatar
Avatar
niw
migratorはwithUnsafeContinuationを使うように書き換える?
omochimetaru 6/8/2021 3:26 AM
あーそうか、そのはずですね。
Avatar
なるほど
Avatar
Kishikawa Katsumi 6/8/2021 4:23 AM
UISheetPresentationControllerって意外とiOS 13くらいからいたのか。。。?
Avatar
プライベートだったんじゃなかったでしたっけ
Avatar
Kishikawa Katsumi 6/8/2021 4:26 AM
そうそう。プライベートで。
4:27 AM
ランタイムヘッダーのダンプかクラッシュのスタックトレースが検索にめっちゃ出てくる
Avatar
ww
Avatar
Kishikawa Katsumi 6/8/2021 4:27 AM
そうか、ずっといたのか〜
Avatar
たぶん Mail.app の Compose とかずっとそれ使ってそうw
Avatar
Kishikawa Katsumi 6/8/2021 4:36 AM
なるほど。確かに。
Avatar
@Kishikawa Katsumi @noppe @rintaro さっきspaceで話していたやつ struct A { enum B { case c(d: D) } } みたいなことをやるとdが緑色にhighlightされる
Avatar
手元では再現しないっぽいです
Avatar
なるほど。ちなみに @_exported がハイライトされなくなってました
👍 1
Avatar
同じの観測してた。でもdependenciesがハイライトされないからなんかおかしい気がしてた。
Avatar
わーお
Avatar
Avatar
d_date
@Kishikawa Katsumi @noppe @rintaro さっきspaceで話していたやつ struct A { enum B { case c(d: D) } } みたいなことをやるとdが緑色にhighlightされる
うーん、コンパイルエラーがでちゃってるのを直してから出直してみます
7:17 AM
ちなみにこんな感じになる
Avatar
なるほどおかしいですね。
Avatar
自分もコンパイルエラー出ているからそれかもしれないw
Avatar
Platform state of the unionのセッションのコードも引数ラベルが緑になってる (edited)
Avatar
Kishikawa Katsumi 6/8/2021 3:00 PM
asyncのプロパティも結局入ったんですね。
👀 1
Avatar
Avatar
shiz
今は async {} -> Taskのinit detach -> Task.detach に変わってますね(だいぶ議論になってますが) https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md#unstructured-tasks-1 https://github.com/apple/swift/pull/37495 違いとしてはざっくりと
  • Taskのinit -> 呼び出し側のmeta情報やpriorityなどを引き継ぐ
  • Task.detach -> ↑を引き継がない
なんですかね https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md#context-inheritance 僕はasyncHandlerの代わりだと思ってます。 We might need to create new tasks whose lifetime is not bound to the creating task, for example in order to fire-and-forget some operation or to initiate asynchronous work from synchronous code
(edited)
async {} -> Taskのinit
"Meet async/await in Swift" では async として紹介されてたんですが、 WWDC のビデオの情報が古いですか?(↓の async のことですよね?) https://developer.apple.com/videos/play/wwdc2021/10132/?time=1385
Swift now supports asynchronous functions — a pattern commonly known as async/await. Discover how the new syntax can make your code...
Avatar
Avatar
koher
async {} -> Taskのinit
"Meet async/await in Swift" では async として紹介されてたんですが、 WWDC のビデオの情報が古いですか?(↓の async のことですよね?) https://developer.apple.com/videos/play/wwdc2021/10132/?time=1385
はい、最初のbetaは(WWDCのビデオも)まだ古いままのようです。 For reference, here is the full list of concurrency-related proposals included in the first beta. Note, in some cases there can be lag between a proposal being updated in open source and it making it into the build, so some proposal amendments are not reflected in the first beta. For example, beta 1 still requires async { } to launch an unstructured async task rather than the now-proposed Task { }. https://forums.swift.org/t/swift-concurrency-feedback-wanted/49336
Today Apple released the first beta of Xcode 13. This includes Swift 5.5, with support for language-native concurrency. Most of these features have already been accepted as evolution proposals, as well as a few that are still in review. Swift Concurrency is a huge feature, by far the biggest change to the language that has been through the evol...
🙏 1
Avatar
Avatar
shiz
はい、最初のbetaは(WWDCのビデオも)まだ古いままのようです。 For reference, here is the full list of concurrency-related proposals included in the first beta. Note, in some cases there can be lag between a proposal being updated in open source and it making it into the build, so some proposal amendments are not reflected in the first beta. For example, beta 1 still requires async { } to launch an unstructured async task rather than the now-proposed Task { }. https://forums.swift.org/t/swift-concurrency-feedback-wanted/49336
ObservableObject とか WWDC 後に派手に変更されたのはありましたが、発表時からすでに情報が古いのは新しいですね😅
😅 1
Avatar
WWDC直前にかわったのかな? (edited)
😭 1
Avatar
5.5に入ったのは10日前くらいですね https://github.com/apple/swift/pull/37680
The Task type has oscillated somewhat from being purely a namespace, to having instances that are used (albeit rarely), back to purely being a namespace that isn&#39;t used for all that many na...
Avatar
スライドの修正やビデオの撮影・編集を考えると間に合わなさそうですね💦
Avatar
10日前は厳しそうw
Avatar
オフラインなら修正できたかもですが。
12:51 AM
まあでもそもそも beta に入ってないからダメか。
Avatar
ですね😅そしてこの変更に対してもまた色々な意見が 出ている状態です。
Avatar
この1年はまあ実戦投入きびしそうだし、様子見かなあ...
Avatar
そうですね…あとはiOS15+の制限がやはり厳しいなぁ、と感じてます。 https://forums.swift.org/t/will-swift-concurrency-deploy-back-to-older-oss/49370
Maybe this is not the place to ask since is Apple specific but I'm sure a lot of folks are wondering: will the async features be backwards deployable or only work on the new OSs?
😢 1
Avatar
At this time, folks should assume that concurrency does not backward deploy. That said, everyone is aware of the value of it doing so, and is something that is being explored/considered.
12:56 AM
これなー。
Avatar
iOS 14 以下で使えるようにならないと当分先のお楽しみですね😢
Avatar
omochimetaru 6/9/2021 3:08 AM
サーバーサイドで使おう!
Avatar
会社だとAndroidもやってる影響で片手間サーバーサイドがだいたいKotlin… (edited)
Avatar
omochimetaru 6/9/2021 3:11 AM
KotlinはAndroidもサーバーもasync/await使えますね。
Avatar
KotlinはSpring転用できるから現実的だし良い選択肢ですね
Avatar
omochimetaru 6/9/2021 3:12 AM
Swiftのとは違って await を付けないからどこがasyncなのかコードからわからないのと、 try - throws も無いからどれが例外投げるのかわからん という違いはあるけど。
🙃 1
Avatar
どこがasyncなのかコードからわからない
AndroidStudio使う前提みたいなのはあるので、エディタ側で表示してくれるのでまあとは思いますね
Avatar
omochimetaru 6/9/2021 3:13 AM
あれ、表示されたっけ?
Avatar
左ににょろマークがでます
Avatar
omochimetaru 6/9/2021 3:14 AM
やったときは気づかなかったな。
Avatar
Kotlin が Java の検査例外捨ててしまったの悲しい。
Avatar
なんかこういう→が出る
😊 1
Avatar
検査例外とasync、コンパイラ側が勝手にやってエディタ側で表示するという世界線がありえるのか(重そう)
Avatar
omochimetaru 6/9/2021 3:16 AM
むむ、それはあったら気づいたはずだ、俺が触った時はなかったとかありえそう AS結構アプデどんどんあるし。
3:16 AM
とはいえIDEで気づけるならいいですね。
Avatar
ガチIDE屋さんが作ってるのはつよい…
Avatar
omochimetaru 6/9/2021 3:16 AM
認識を改めた
Avatar
にょろ
3:16 AM
チルダ
Avatar
このkotlinのIDEによるサポートは、例外への対応もあるんですか? (edited)
3:17 AM
そもそも関数の定義側に宣言がないと使えないからだめか
Avatar
Avatar
omochimetaru
認識を改めた
うーん、でも表示上気付けるのと、コード書いた人が自分の意思で明示的に許可するのはやっぱワンステップ違うんだよなぁ。
Avatar
Avatar
tarunon
そもそも関数の定義側に宣言がないと使えないからだめか
omochimetaru 6/9/2021 3:18 AM
あーそうか。asyncはあるけどthrowsはないのか。
Avatar
Avatar
tarunon
このkotlinのIDEによるサポートは、例外への対応もあるんですか? (edited)
これはなさそうですねそういうアノテーションあるかどうかは知らないですが
Avatar
Avatar
tarunon
検査例外とasync、コンパイラ側が勝手にやってエディタ側で表示するという世界線がありえるのか(重そう)
omochimetaru 6/9/2021 3:19 AM
歴史的に、IDEでやっていくパラダイムが覇権だったけど、 Swiftが、最初から言語仕様にしたらよくね?って更に世代を進めた印象がある。
Avatar
Avatar
tarunon
そもそも関数の定義側に宣言がないと使えないからだめか
ですね。 Kotlin の suspendasync しかない状態だけど、エラーハンドリングについては Swift で言う throwstry もない状態。
Avatar
Avatar
omochimetaru
歴史的に、IDEでやっていくパラダイムが覇権だったけど、 Swiftが、最初から言語仕様にしたらよくね?って更に世代を進めた印象がある。
コンパイラがチェックする async/await は C# からあるのでは?
3:20 AM
コルーチンベースではないけど。
Avatar
Avatar
koher
コンパイラがチェックする async/await は C# からあるのでは?
omochimetaru 6/9/2021 3:20 AM
C# の async はまたちょっと違うんすよね。
Avatar
(こうしてみると、Discordのリプライはスレッドにまとめてほしくなっちゃうな)
Avatar
omochimetaru 6/9/2021 3:21 AM
返り値のシグネチャが async かつ Task<T> を返すという条件があって、 (edited)
Avatar
(TwitterのリプライツリーはUIとしてよくできていた。) (edited)
Avatar
omochimetaru 6/9/2021 3:21 AM
await しなくても Task を受け取る式としてそのままにできる。
Avatar
(サービスとしてはのこってる)
Avatar
Avatar
tarunon
(こうしてみると、Discordのリプライはスレッドにまとめてほしくなっちゃうな)
スレッド、もうすぐ来るらしいですよ (APIドキュメントだけあるw)
👀 1
Avatar
omochimetaru 6/9/2021 3:22 AM
あーいや、 async はcalleeの内部で await ができるようになる + 返り値をTaskかvoidに強制するだけで、 caller には影響を与えていない。 (edited)
3:22 AM
Task 型に対して await オペレータが使える、という構成です
3:23 AM
TaskからTを取り出すところに必ずawaitを書くので、suspension pointはわかりますね。
Avatar
うん、形は違うけど、 await をコンパイラが扱うという意味では。
3:23 AM
Swift はそれをエラーハンドリングのときに try で手を入れてて、
Avatar
omochimetaru 6/9/2021 3:24 AM
えっとそれだとJSもそうですね。 IDEうんぬんの話はasync/awaitに限らず、言語機能全般に対するトレンドに対して言いました。
Avatar
それは Java の検査例外にもなくて、 Kotlin はその概念を手にしてなかったから suspend の call site 側の修飾子がないままになってしまったのかな。
Avatar
omochimetaru 6/9/2021 3:25 AM
うーん、それは微妙ですね
3:25 AM
TypeScript/JSも、例外は投げっぱなしだけど、awaitは明示的なので。 (edited)
3:25 AM
例外のマーキング性が非同期のマーキング性になるとは限らない
Avatar
でもそれらの async/await は↑で語られてるように Swift や Kotlin のコルーチンベースのものとはちょっと違ってて、
3:27 AM
Kotlin の suspend はより throws に近いはずだったんだけど、
Avatar
omochimetaru 6/9/2021 3:27 AM
あー、なるほど。
Avatar
もし Kotlin に検査例外があって、さらに try のマーキングが必要だったら
Avatar
omochimetaru 6/9/2021 3:27 AM
suspendableな関数としてのcoroutineが言語仕様にあるのは Swift, Kotlinで、
Avatar
suspend の call site にもマークが必要と気づいた気が。
Avatar
omochimetaru 6/9/2021 3:28 AM
C#とTypeScriptのawaitはcorountineではなくTaskやPromiseオブジェクトに対するオペレータで、ノリが違うと。
Avatar
ですね。
Avatar
yutailang0119 6/9/2021 8:57 AM
func request<R: Request>(of request: R) async throws -> R.Response func request<R: Request>(of request: R) async -> Result<R.Response, Error> みたいな実装をした時に、tryの有無だけでは Ambiguous use of は解決できんのね
Avatar
そこで @_disfavoredOverload (edited)
Avatar
omochimetaru 6/9/2021 8:58 AM
できなそう てか、後者だけあれば、 request(of: ...).get() が前者と同じだし要らないような
Avatar
(できるかな)
Avatar
yutailang0119 6/9/2021 8:59 AM
実際には後者はエラーの型を縛りたい
Avatar
omochimetaru 6/9/2021 9:00 AM
Swift.Error のときしか get() ないんだっけ。
Avatar
yutailang0119 6/9/2021 9:02 AM
いや、そんなことないと思う
9:02 AM
asyncでエラーも起きるメソッドがthrowsするかResultをかえすかが各所で議論されてて考えてた
Avatar
omochimetaru 6/9/2021 9:03 AM
asyncかどうかで変わらないと思うんだよな〜
9:03 AM
今までのthrowsかResultかと同じ考え方で良いと思う。
Avatar
yutailang0119 6/9/2021 9:05 AM
たしかに
Avatar
Avatar
shiz
はい、最初のbetaは(WWDCのビデオも)まだ古いままのようです。 For reference, here is the full list of concurrency-related proposals included in the first beta. Note, in some cases there can be lag between a proposal being updated in open source and it making it into the build, so some proposal amendments are not reflected in the first beta. For example, beta 1 still requires async { } to launch an unstructured async task rather than the now-proposed Task { }. https://forums.swift.org/t/swift-concurrency-feedback-wanted/49336
この話、 Task になったら _ = Task { } が強制されるかと思ったけど、イニシャライザにも @discardableResult 付けられるんですね。考えたことなかった。 @swift-5.4.3 struct Foo { @discardableResult init(_ handler: () -> Void) { handler() } } Foo { print("hello") }
Avatar
hello
Avatar
@swift-5.4.3 struct Foo { //@discardableResult init(_ handler: () -> Void) { handler() } } Foo { print("hello") }
Avatar
hellostderr:<stdin>:8:1: warning: result of 'Foo' initializer is unused Foo { ^ ~
Avatar
インスタンスを生成するためのイニシャライザなのにインスタンスを discard するのおもしろい。
😆 2
😲 1
Avatar
I figured I should at least start a PR instead of being lazy. Fixes rdar://65258964.
👀 1
Avatar
Kishikawa Katsumi 6/10/2021 1:05 PM
Right now the supported deployment target is iOS 15, macOS Monterey, etc., or later. This is because of enhancements to Dispatch to support Swift concurrency, of which the concurrency runtime uses. We are actively exploring the possibility of backward deployment, but are mindful of not compromising the future of concurrency performance by doing so.
これはまあ期待して良さそうな気がする。
1:06 PM
async/awaitがiOS 14で使えないの?という質問に対して。
Avatar
omochimetaru 6/10/2021 1:12 PM
実現できるか検討中、なるほど。
Avatar
Kishikawa Katsumi 6/10/2021 2:57 PM
Actorが作られるオーバーヘッドはコンパイラとランタイムでかなり最適化されるからすごく少ないよっていうQ&Aもよかった。
Avatar
omochimetaru 6/10/2021 2:57 PM
らしいですね〜 DispatchQueueで自分で書くのと違って。
Avatar
Xcodeのplaygroundでasync/awaitってつかえないんですかね
Avatar
omochimetaru 6/10/2021 2:58 PM
13なら使えると思います
Avatar
macOS 12にしないとだめ?
2:58 PM
昨日寝る直前にためしてなんか使えなかった…
Avatar
omochimetaru 6/10/2021 2:58 PM
あーどうなんだ?
2:59 PM
ConcurrencyはOSのランタイム使うから確かに。
Avatar
iOSならイケるのかな
Avatar
omochimetaru 6/10/2021 2:59 PM
iOS15beta入れないと・・・
2:59 PM
iOS Simulatorが楽そう
Avatar
iOSターゲットなplaygroundはSimulatorが動いてるわけじゃないんだっけ。
Avatar
omochimetaru 6/10/2021 3:00 PM
playgroundはsimulatorですね、お、それがいいか
Avatar
#xcode だったかもしれないこの話題は
3:00 PM
…とおもってiOSなplaygroundにしたんだけど、なんか使えなかったんだよなあ…
Avatar
import _Concurrency 書くと使えます?
Avatar
Avatar
rintaro
import _Concurrency 書くと使えます?
やってみまsu
Avatar
import _Concurrency import Foundation async { let (dat, _) = try await URLSession.shared.data(from: URL(string: "https://www.google.com")!) print(String(decoding: dat, as: UTF8.self)) } とりあえずこれは動きました。
Avatar
うごいた...
4:28 PM
えーw
4:29 PM
FBした方がいい感じ
4:29 PM
なお macOS の場合
Avatar
既知だとは思いますが、一応 🙏
Avatar
Done FB9155068
👍 1
Avatar
protocol Ring {} protocol MatrixImpl { associatedtype BaseRing: Ring } struct DefaultMatrixImpl<A: Ring>: MatrixImpl { typealias BaseRing = A } struct Matrix<A, B: MatrixImpl> where B.BaseRing == A {} extension Matrix where B == DefaultMatrixImpl<A> {} // Redundant conformance constraint 'B': 'MatrixImpl' <- huh? 最後の extension で redundant だと警告が出るんですが,警告が間違ってますよね? (edited)
8:46 AM
想定している状況は、行列の実装を係数環(整数・有理数 etc)ごとに変えられるようにしたくて、行列の実装が特定の型の場合にインターフェースも拡張できるようにしたい、というものです。
Avatar
extension Matrix where B == DefaultMatrixImpl<A> {} においてMatrixの制約からA == B.BaseRingとなるので、 B == DefaultMatrixImpl<B.BaseRing>となって循環しているのではないでしょうか
Avatar
Avatar
Taketo Sano
protocol Ring {} protocol MatrixImpl { associatedtype BaseRing: Ring } struct DefaultMatrixImpl<A: Ring>: MatrixImpl { typealias BaseRing = A } struct Matrix<A, B: MatrixImpl> where B.BaseRing == A {} extension Matrix where B == DefaultMatrixImpl<A> {} // Redundant conformance constraint 'B': 'MatrixImpl' <- huh? 最後の extension で redundant だと警告が出るんですが,警告が間違ってますよね? (edited)
Miwa / Ensan 6/13/2021 9:02 AM
Swift5.5のβだと特に警告は出ていません
Avatar
おぉ,なるほど… 5.5 で解消されるのですね。
Avatar
@swift-5.4.3 @swift-main protocol Ring {} protocol MatrixImpl { associatedtype BaseRing: Ring } struct DefaultMatrixImpl<A: Ring>: MatrixImpl { typealias BaseRing = A } struct Matrix<A, B: MatrixImpl> where B.BaseRing == A {} extension Matrix where B == DefaultMatrixImpl<A> {} // Redundant conformance constraint 'B': 'MatrixImpl' <- huh?
Avatar
swiftNightly BOT 6/13/2021 9:04 AM
no output
Avatar
stderr:<stdin>:10:26: warning: redundant conformance constraint 'B': 'MatrixImpl' extension Matrix where B == DefaultMatrixImpl<A> {} // Redundant conformance constraint 'B': 'MatrixImpl' <- huh? ^ <stdin>:10:26: note: conformance constraint 'B': 'MatrixImpl' implied here extension Matrix where B == DefaultMatrixImpl<A> {} // Redundant conformance constraint 'B': 'MatrixImpl' <- huh? ^
Avatar
おお、ほんとですね。 < Swift 5.5
Avatar
循環してる感じは確かにするんですが,そうしないと extension が使えないんですよね… 本当は parametrized extension を使ってこう書きたい: protocol Ring {} protocol MatrixImpl { associatedtype BaseRing: Ring } struct SomeRing: Ring {} struct Matrix<B: MatrixImpl> {} struct DefaultMatrixImpl<A: Ring>: MatrixImpl { typealias BaseRing = A } extension<A: Ring> Matrix where B == DefaultMatrixImpl<A> {} (edited)
Avatar
Miwa / Ensan 6/13/2021 9:12 AM
なるほど、Aはダミーの型パラメータなんですね
Avatar
はい,そうすればできるかなと思ってやってみたら警告が出てしまいまして🤔
9:13 AM
でもこういうトリッキーなことはしない方がいいのかもしれません🤔
Avatar
Miwa / Ensan 6/13/2021 9:14 AM
ワークアラウンドですが、これだとまずい状況でしょうか protocol Ring {} protocol MatrixImpl { associatedtype BaseRing: Ring } struct DefaultMatrixImpl<A: Ring>: MatrixImpl { typealias BaseRing = A } struct Matrix<B: MatrixImpl> {} // DefaultMatrixImplのみDefaultMatrixImplProtocolに適合させる protocol DefaultMatrixImplProtocol { associatedtype BaseRing: Ring } extension DefaultMatrixImpl: DefaultMatrixImplProtocol {} extension Matrix where B: DefaultMatrixImplProtocol {} (edited)
Avatar
それだと大丈夫ですね.ただちょっとこの方法で protocol を増やすのも抵抗があるので,別の方法を考えようと思います.ありがとうございます🙏
Avatar
Miwa / Ensan 6/13/2021 9:18 AM
なるほど、失礼しました🙏
🙇‍♂️ 1
Avatar
Miwa / Ensan 6/13/2021 9:25 AM
元の挙動がおかしいので直すのも妙だと思いますが、これだと5.4でも警告が出ませんでした。 protocol Ring {} protocol MatrixImpl { associatedtype BaseRing: Ring } struct DefaultMatrixImpl<A: Ring>: MatrixImpl { typealias BaseRing = A } struct Matrix<A, B: MatrixImpl> where B.BaseRing == A { typealias A = A typealias B = B } extension Matrix where Self.B == DefaultMatrixImpl<Self.A> {} (edited)
Avatar
@Taketo Sano Parameterized Extension が使えるようになるまで↓でごまかすのはダメですか? extension Matrix { func foo<A: Ring>() -> Foo where B == DefaultMatrixImpl<A> { ... } } (edited)
9:27 AM
@swift-5.4.3 protocol Ring {} protocol MatrixImpl { associatedtype BaseRing: Ring } struct SomeRing: Ring {} struct Matrix<B: MatrixImpl> {} struct DefaultMatrixImpl<A: Ring>: MatrixImpl { typealias BaseRing = A } struct Foo {} extension Matrix { func foo<A: Ring>() -> Foo where B == DefaultMatrixImpl<A> { Foo() } }
Avatar
no output
Avatar
そうですね,今回は initializer を拡張したいだけだったので,toXXX 的な instance method を生やすか,init 代わりの static method を生やすかに変えようと思います.ありがとうございます😊
Avatar
これで行こうと思います! protocol Ring {} protocol MatrixImpl { associatedtype BaseRing: Ring } struct SomeRing: Ring {} struct Matrix<Impl: MatrixImpl> { init(_ impl: Impl) {} } struct DenseMatrixImpl<A: Ring>: MatrixImpl { typealias BaseRing = A } struct SparseMatrixImpl<A: Ring>: MatrixImpl { typealias BaseRing = A } extension Matrix { func toSparse<A: Ring>() -> Matrix<SparseMatrixImpl<A>> where Impl == DenseMatrixImpl<A> { .init(SparseMatrixImpl<A>()) } func toDense<A: Ring>() -> Matrix<DenseMatrixImpl<A>> where Impl == SparseMatrixImpl<A> { .init(DenseMatrixImpl<A>()) } }
👀 1
🙂 1
Avatar
method を private にしとくと compiler が良い感じに inline 化してくれたりするのだろうと期待しているのですが,実際に private にするのと public にして @ inlinable などをつけるのではどちらが速くなるかといったことは知見などありますか?
Avatar
Avatar
Taketo Sano
method を private にしとくと compiler が良い感じに inline 化してくれたりするのだろうと期待しているのですが,実際に private にするのと public にして @ inlinable などをつけるのではどちらが速くなるかといったことは知見などありますか?
インライン化は public でも同一モジュール内であれば勝手にされるはずですね。モジュールをまたぐときは @inlinablehttps://github.com/apple/swift-evolution/blob/main/proposals/0193-cross-module-inlining-and-specialization.md が必要になります。
Avatar
Avatar
koher
インライン化は public でも同一モジュール内であれば勝手にされるはずですね。モジュールをまたぐときは @inlinablehttps://github.com/apple/swift-evolution/blob/main/proposals/0193-cross-module-inlining-and-specialization.md が必要になります。
ふーむ,なるほど… 実感としては public + inlinable が明らかに速くなってるような気がするんですが,protocol extension を色々やってる影響ですかねぇ…🤔
Avatar
クロスモジュールの場合、 private メソッドがインライン化されてない等あり得ると思います。 (edited)
Avatar
private なのに inline 化してくれないんです?
Avatar
omochimetaru 6/14/2021 8:17 AM
privateinline 化可能なはずです。 可能かどうかとは別に、 @inlineable をつけることで、インライン化されやすくなるかどうかは知らないです。同じだと思ってますけど・・・
8:17 AM
具体的に @inlineable がやってるのは、関数の中身をライブラリヘッダーに書き出すという事です
8:18 AM
通常の状態だと関数のシグネチャのみが見えていて、中身が見えないので、インライン化できないのですが、 @inlineable をつけると、インライン化できるように、中身も露出するという仕組みです。
8:18 AM
private メソッドはそもそも同一モジュール内からしか呼び出せなくて、同一モジュール内についてはコンパイル時に中身が見えているので、付けなくても同じはずなんです。
Avatar
inlineable をつけるには method を public にしなきゃいけないのが嫌な場合が多くて,private にしとけばコンパイラが賢くやってくれるのが一番なのですが,public + inlineable の方が速くなるようなケースがある感じがしてまして…
Avatar
omochimetaru 6/14/2021 8:19 AM
インライン化するかどうかの判断に影響を与えるのは @_inline(always), @_inline(never) などがありますね。
8:20 AM
そのメソッドがインライン化されるかどうかとは別の話として、
8:20 AM
そのメソッドを呼び出している別のメソッドとまとめてインライン化できるかどうか、というのが変わってきますね
8:21 AM
public struct S1 { @inlineable public func f2() { f3() } private func f3() { compute() } } (edited)
8:24 AM
例えばこうなってたとき、 f2を呼び出す外部モジュールにおいては、f2の中のf3はインライン展開されなかった気がします。
8:24 AM
で、f2の中のf3のインライン展開も怪しい気がします。↑の話があるので。
8:25 AM
@usableFromInline というのがあって
8:25 AM
public struct S2 { @inlineable public func f2() { f3() } @usableFromInline private func f3() { compute() } }
8:26 AM
こうすると、 f2の中にf3はインライン展開されるし、 f2をインライン展開する外部のモジュールにおいて、f3もインライン展開される、って事だったと思います。
8:26 AM
このへんかなりややこしくてちょっと自信ないですけど。
8:26 AM
public + inlineable は、 ↑の @usableFromInline と同じ状態になるので
8:26 AM
差が出ているならそういうことかもしれません。
Avatar
Avatar
omochimetaru
public struct S1 { @inlineable public func f2() { f3() } private func f3() { compute() } } (edited)
そもそもこれはコンパイルできないですね。 @swift-main public struct S1 { @inlinable public func f2() { f3() } private func f3() { } } (edited)
Avatar
Avatar
omochimetaru
public + inlineable は、 ↑の @usableFromInline と同じ状態になるので
Proposal 読んでたんだけど
The @usableFromInline attribute can only be applied to internal declarations. It does not make sense on public declarations, which are already ABI-public. It also cannot be applied to private and fileprivate declarations.
Avatar
swiftNightly BOT 6/14/2021 8:27 AM
exit status: 1 with stderr:<stdin>:4:5: error: instance method 'f3()' is private and cannot be referenced from an '@inlinable' function f3() ^ <stdin>:7:16: note: instance method 'f3()' is not '@usableFromInline' or public private func f3() { ^ <stdin>:8:5: error: cannot find 'compute' in scope compute() ^~~~~~~
Avatar
Avatar
Yuta Saito
そもそもこれはコンパイルできないですね。 @swift-main public struct S1 { @inlinable public func f2() { f3() } private func f3() { } } (edited)
omochimetaru 6/14/2021 8:27 AM
ああ、できないか。それをできるようにするために @usableFromInline が出てくるんだね。
Avatar
private@usableFromInline 使えないんだっけ?
Avatar
Avatar
koher
Proposal 読んでたんだけど
The @usableFromInline attribute can only be applied to internal declarations. It does not make sense on public declarations, which are already ABI-public. It also cannot be applied to private and fileprivate declarations.
omochimetaru 6/14/2021 8:27 AM
internalじゃなきゃだめか。
Avatar
で、 @usableFromInline って @inlinable から呼び出せるだけであって
Avatar
omochimetaru 6/14/2021 8:28 AM
どうせABI可視性をぶっ壊す(そしてABI互換性の担保をほぼ無理にする)ので付けられても良さそうですけどね。 (edited)
Avatar
インライン化したいならその internal なメソッドに @usableFromInline じゃなくて @inlinable 付けるんじゃないっけ?
Avatar
omochimetaru 6/14/2021 8:29 AM
あー、 @usableFromInline は呼び出せるだけか。
8:30 AM
コンパイルできないのができるようになる(ただし普通に呼び出すコードが出る)か
Avatar
Avatar
Taketo Sano
inlineable をつけるには method を public にしなきゃいけないのが嫌な場合が多くて,private にしとけばコンパイラが賢くやってくれるのが一番なのですが,public + inlineable の方が速くなるようなケースがある感じがしてまして…
なので
inlineable をつけるには method を public にしなきゃいけないのが嫌な場合が多くて
については、 public じゃなくて internal にして @inlinable つければとりあえずいいのかな?
Avatar
@inlinableから呼び出すinternal関数を更にinline化するためのアトリビュートが@transparentだったはず
👀 1
Avatar
omochimetaru 6/14/2021 8:31 AM
transparentってそういうことなのか
Avatar
@transparentは可視性を問わずに付けられたはず
Avatar
それですね
👌 1
Avatar
LLVMのアセンブラも最適化で独自のインライン化を実行するはずなのでそこまで下りないとどうなるかわからない気がする
Avatar
omochimetaru 6/14/2021 8:35 AM
Swiftの関数はLLVM側で勝手にインライン化されることは無い気がします。それがあるとABI保守性が壊れるので
Avatar
↓一つ目から超厳しい制約が書いてある・・・。
When should you use @_transparent? - Does the implementation of this function ever have to change? Then you can't allow it to be inlined.
Avatar
omochimetaru 6/14/2021 8:36 AM
transparent は標準ライブラリでよっぽどなやつに使うやつ用のイメージ
Avatar
- Does the implementation need to call private things---either true-private functions, or internal functions that might go away in the next release? Then you can't allow it to be inlined. - Is it okay if the function is not inlined? You'd just prefer that it were? Then you should use @inlinable, rather than @_transparent. (If you really need this, you can add @inline(__always) as well.)
8:38 AM
今回のケースでは internal + @inlinable が無難な気がしますがどうでしょう?
👍 1
Avatar
そもそもユーザーが提供するライブラリが安定なABIを保証する必要があるのか、という議論もありますが…w
Avatar
omochimetaru 6/14/2021 8:38 AM
それで合ってると思います。
Avatar
Avatar
Yuta Saito
そもそもユーザーが提供するライブラリが安定なABIを保証する必要があるのか、という議論もありますが…w
omochimetaru 6/14/2021 8:39 AM
まあねえ。フルリビルドしてくださいでいいよねえ。
Avatar
Avatar
Yuta Saito
そもそもユーザーが提供するライブラリが安定なABIを保証する必要があるのか、という議論もありますが…w
そうですね。どうせビルドすればいいし。
Avatar
usableFromInline と inlineable の違いがいまひとつ分かっていないです🤔
Avatar
omochimetaru 6/14/2021 8:41 AM
usableFromInlineは僕の説明が間違ってたのでまずその話は忘れてください
Avatar
もし、コードサイズの肥大化に躊躇がない&ABI安定を必要としない場合、評価関数によってInline化されないケースが有るinlinableより、絶対にインライン化される@_transparentの方が好ましい場合がありそうです。
Avatar
Avatar
Yuta Saito
もし、コードサイズの肥大化に躊躇がない&ABI安定を必要としない場合、評価関数によってInline化されないケースが有るinlinableより、絶対にインライン化される@_transparentの方が好ましい場合がありそうです。
omochimetaru 6/14/2021 8:42 AM
評価関数とどっちが賢いかは微妙じゃない?
8:42 AM
コードサイズが肥大化して、ローカル変数がレジスターに乗り切らなくなる場合とかだと
8:42 AM
関数ジャンプしたほうが早いってことがありそう
8:42 AM
その場合(calleeではなく)callerのコード内容にもよってすべきかどうかが変わってくる (edited)
Avatar
あー、たしかに。単に命令列が長くなるだけじゃなくて、そういうケースもあるか
Avatar
omochimetaru 6/14/2021 8:43 AM
まああとコードサイズとキャッシュページのサイズの関係とか。よほどでかいと。
Avatar
Avatar
Taketo Sano
usableFromInline と inlineable の違いがいまひとつ分かっていないです🤔
@usableFromInline@inlinable な関数から呼び出せるだけですね。名前の通りの説明になってしまいましたが💦 (edited)
8:46 AM
@Taketo Sano クロスモジュールでインライン化されるということはその body が呼び出し側に埋め込まれることになります。そうすると、そのインライン化された関数の中から呼ばれている public でない関数がモジュールを越えて見えないといけないということになります。そのためには public でなくても ABI を公開しないといけなくて、それを可能にするのが @usableFromInline です。
8:47 AM
// Module A import B func a() { b() } // Module B @inlinable public func b() { print("b") _b() } @usableFromInline internal func _b() { print("_b") }
8:48 AM
↑の場合に ab を利用している箇所がインライン化された場合、↓のようになるイメージです。 func a() { print("b") _b() }
8:49 AM
一方でもし @usableFromInline@inlinable でフルにインライン化されたら↓のようなイメージです。 func a() { print("b") print("_b") }
8:50 AM
@usableFromInline の例では a の中から _b を呼ばないといけないので internal_b の ABI がモジュールを越えて公開されていなければなりません。それを可能にするのが @usableFromInline です。
👌 3
8:51 AM
という理解です。間違いがあれば指摘下さい。
Avatar
ふむふむ,なるほど!
Avatar
TypeScript で await 忘れやらかして 30 分くらい悩んでた。やっぱり Swift の await 強制はすばらしい・・・。
Avatar
返り値未使用の警告出なかったですか?Voidだった? (edited)
Avatar
Web API で await なメソッドの戻り値を JSON にして返してたんだけど、空のオブジェクトになってておかしいなと思って、クラウドの API だったからパーミッションまわりを疑って権限付与されてるかとか調べてた(実際権限正しく与えてられてなかったから与え直したんだけどうまく動かなくて悩んだり)。そしたら Promise{} になってただけだった。 (edited)
Avatar
返り値を使ってるけど駄目だったパターンかあ。 JSONだったからany型になってて、Promise型がそれにハマってしまったのかな。
Avatar
↓みたいな感じ。 const value = getValueAsync(); const responseValue = JSON.stringify(value);
Avatar
valueが型推論でPromiseになってるけどstringifyがなんでも受け付けるからチェックできなかったのか。 (edited)
Avatar
うん。
Avatar
これはハマる。
Avatar
value に型を書いてれば tsc が救ってくれたんだろうけど・・・。
Avatar
Swiftだったら(もしawaitが必須じゃなくても)stringifyのところでEncodable conformanceがなくて、そこで止まってそうだし
10:25 AM
2つのゆるさがかけ合わさって見つかりにくいやつだ
Avatar
たしかに。
Avatar
以前Koherさんの記事にコメントさせていただいたんですが、これどう思われますか? https://qiita.com/koher/items/338d2f2d0c4731e3508f#comment-668fc5304cebad8ca60a
Swift 5.1 で Opaque Result Type (SE-0244) が導入されます。 Opaque Result Type とは何でしょうか。例を見てみましょう。次のような Animal と Cat があるとします。 ...
👀 1
Avatar
Avatar
Miwa / Ensan
以前Koherさんの記事にコメントさせていただいたんですが、これどう思われますか? https://qiita.com/koher/items/338d2f2d0c4731e3508f#comment-668fc5304cebad8ca60a
すみません、完全に通知に埋もれて気付いてませんでした。
2:38 PM
ちゃんと読んでから返事しますね。
Avatar
Miwa / Ensan 6/14/2021 2:53 PM
そうかなと思っていました、急かすような形でごめんなさい🙏
Avatar
omochimetaru 6/17/2021 4:07 AM
@rzidane360 Swift concurrency doesn’t use green threads; switching between tasks pretty much just means returning from the current function that was running the old task and calling the resumption function for the new task, plus a tiny amount of bookkeeping
4:07 AM
おもしろい スレッドが続いてる (edited)
Avatar
ほー
Avatar
omochimetaru 6/17/2021 4:19 AM
スケジュールにスレッドを使わないから、事前に用意されたスレッドの上で動くexecutorがひたすら待機してる次のコルーチンを呼び出すループをしてるだけで、コンテキストスイッチも起きないし、 コルーチンの中断はスレッドを止めないから、スレッドも止まらないし、 コルーチンの内部実装はどんどん次の関数ポインタを返していく仕組みだから小さい関数を繰り返し呼んでいくだけだ。
👏 1
Avatar
サスペンションポイントが静的に決定できることとタスク内でスレッドをブロックしないという仮定が上手く使われた仕組みっぽい
Avatar
omochimetaru 6/17/2021 4:24 AM
nodejsがやっていたコールバック関数チェーンだけで全部並行処理をやるって世界観を、完全に言語レベルで組み込んだ感じ。
4:26 AM
ローカル変数も必要なければスタックに置くらしいし。
Avatar
かしこい
Avatar
Avatar
Yuta Saito
サスペンションポイントが静的に決定できることとタスク内でスレッドをブロックしないという仮定が上手く使われた仕組みっぽい
omochimetaru 6/17/2021 4:27 AM
スレッドをブロックしないという仮定
多分これはしばらく死人が出そう
Avatar
セマフォとか使われると死んじゃう
4:30 AM
まぁ他の言語のconcurrency機能も似たような仮定があるだろうし、他言語触ってれば死ななそう
Avatar
omochimetaru 6/17/2021 4:30 AM
いや、無いんじゃないかな?
4:30 AM
C# では、良くないですよってぐらい。
4:31 AM
JS は、呼び出せるAPIにブロッキングが一つも無いことで実現してる
Avatar
呼び出せるAPIにブロッキングが無くてもユーザーがビジーウェイトとかしたらイベントループがブロックされちゃいません?なのでJSは同じような仮定があると思ってました。 (edited)
Avatar
omochimetaru 6/17/2021 4:35 AM
うーん、まあそれはそうだけど、それ言うとJS環境はシングルスレッドだからなあ。
4:35 AM
並行性が最初から無い・・・
4:35 AM
Window.confirm() メソッドは、メッセージと、OK, キャンセルの 2 つのボタンを持つモーダルダイアログを表示します。
Avatar
まあConcurrency関係なしにブロックしたら死んじゃうのはそうw
Avatar
omochimetaru 6/17/2021 4:35 AM
同期でYES/NOを待つ。
Avatar
あー、そうかそのへんの古のAPIはブロッキングだ
Avatar
Avatar
Yuta Saito
まあConcurrency関係なしにブロックしたら死んじゃうのはそうw
omochimetaru 6/17/2021 4:35 AM
正しいけど、ひとつ下の次元で実現しているというかw
Avatar
古のapiがブロッキングなのとブラウザ側からjsを割り込ませる仕組みの組み合わせで
Avatar
omochimetaru 6/17/2021 4:37 AM
semaphoreとかが出てくるのは、まずthread base concurrencyがあって、そこで制御したくてだからなので
4:37 AM
JSに慣れてるとまあ最初からそれをやってしまうことはないかも。 (edited)
Avatar
止まった時の中を動くみたいなコードが書けて面白いんだが、swiftでもそういうの書けたりするのかな。マルチスレッド持ってるから単一プログラムの中で実現しそう
Avatar
Avatar
tarunon
止まった時の中を動くみたいなコードが書けて面白いんだが、swiftでもそういうの書けたりするのかな。マルチスレッド持ってるから単一プログラムの中で実現しそう
postMessageで非同期にJS <-> ネイティブ通信するんじゃなくてconfirmとかをフックして同期で通信するみたいな話ですか?
Avatar
omochimetaru 6/17/2021 4:40 AM
それ自体はsemaphreで書けるね
4:40 AM
関数を結果が来るまでブロックして、 別スレッドでその割り込み処理をやって結果を渡して、 ブロックしてたスレッドを起こす。
Avatar
promptフックとevaluateJavaScripでwebネイティブ同期通信が成り立つよ
Avatar
omochimetaru 6/17/2021 4:41 AM
ただasync/awaitになってからそれをやると、
4:41 AM
他のasync taskが巻き込まれて止まるので崩壊する
Avatar
ふむ
Avatar
omochimetaru 6/17/2021 4:41 AM
自分で立てた割り込みスレッドは動くけど。
4:42 AM
ブロッキングを使った仕組みが、async/awaitで動いてるところに混ざり込むと、並列で動くつもりだったasync達が想定外に巻き込まれて止まる
Avatar
DispatchSemaphore に警告出すとかしないと事故がいっぱい起こらないかな?
Avatar
omochimetaru 6/17/2021 5:28 AM
LIBDISPATCH_COOPERATIVE_POOL_STRICT=1 にすると
5:28 AM
そういうところでクラッシュするようになってくれるらしい
Avatar
XCTestExpectation とかも事故りそう。
Avatar
omochimetaru 6/17/2021 5:29 AM
あれは完全にヤバそうですね。
5:29 AM
.wait するけど、それでスケジューラが止まって、Taskが止まるので、世界が停止してテストが終わらないw
5:29 AM
xctestがasyncになるんじゃないのかしら。throwsになったときみたいに。
Avatar
うん、なるはず。
5:31 AM
でも慣れてない人が XCTTestExpectation と混ぜて死ぬとかありそう。
Avatar
omochimetaru 6/17/2021 5:31 AM
現状のXcode13betaのXCTestframeworkだと特になってないのかな
5:31 AM
まああとすでに書いてあるテストが問題ですね。
5:31 AM
asyncへの段階的以降ができない。
Avatar
まあ、コールバック→ async/await に自動変換された API をテストで元々使ってて expectation 使ってる箇所はコンパイル通らなさそうなので検出できるかな?
Avatar
enum Command: Codable { case load(String) case store(key: String, Int) }.load("MyKey"){ "load": { "_0": "MyKey" } } にエンコードされることになったの、なんで "0" じゃなくて "_0" になったんでしょうか? 0 はラベルにできないから case load(0: String) は作れないので衝突しないけど、 case load(_0: String) は作れて衝突するから "0" をキーにした方が良さそうに思うんですが・・・。何か理由があるんだとは思いますが。 (edited)
Avatar
omochimetaru 6/18/2021 6:27 AM
enum LoadCodingKeys: CodingKey { case _0 }
6:27 AM
のように、ケースごとの構造の方のCodingKeyが作られるからだと思います
6:28 AM
まあ enum LoadCodingKeys: CodingKey { case _0 = "0" } ってことにすることは可能ですけど。
6:28 AM
あー、もしかしたら、
6:29 AM
PHPやJSだと { "0": "a" }["a"] が区別できなくてトラブルの元だから、みたいな事もあるかも?
6:32 AM
提案書には細かい議論が書いてないですねえ。
6:33 AM
このunlabeled parameterは長いこと話が伸びてたトピックの一つだったのを見た気がするのでいろいろありそうですが。
Avatar
なるほど。衝突しうるのは問題な気はするけど、実質的には問題ないだろうし( _ から始まるラベルなんか作らないし)、シンプルに CodingKey を作るところが一番の理由になってそうだね。
Avatar
Miwa / Ensan 6/21/2021 1:24 PM
背景 Swift5.1でOpaque Result Typeという種類の型が追加されました。これは「制約を満たすなんらかの特定の型」を関数が返せるようにする仕組みです。その動作は「リバースジェネリクス」という概念で説明されます。...
Avatar
Avatar
Miwa / Ensan
以前Koherさんの記事にコメントさせていただいたんですが、これどう思われますか? https://qiita.com/koher/items/338d2f2d0c4731e3508f#comment-668fc5304cebad8ca60a
Miwa / Ensan 6/21/2021 1:24 PM
これについて書きました
Avatar
Avatar
Miwa / Ensan
以前Koherさんの記事にコメントさせていただいたんですが、これどう思われますか? https://qiita.com/koher/items/338d2f2d0c4731e3508f#comment-668fc5304cebad8ca60a
遅くなりましたがお返事を書きました。 https://qiita.com/koher/items/338d2f2d0c4731e3508f#comment-6bce387660d7028e2b4d
Swift 5.1 で Opaque Result Type (SE-0244) が導入されます。 Opaque Result Type とは何でしょうか。例を見てみましょう。次のような Animal と Cat があるとします。 ...
🙏 1
4:14 PM
戻り値ジェネリクスに対して引数リバースジェネリクスというのはおもしろいですね。 // 戻り値ジェネリクス func foo<T: Foo>() -> T // 引数リバースジェネリクス func bar(_ x: T) -> <T: Foo> Bar
Avatar
ありがとうございます!
11:28 PM
リバースジェネリックな引数と同じ振る舞いを持つクロージャは今のSwiftでも作ることができます let value: some BinaryInteger = 42 let someClosure = value.isMultiple // someClosure: (some BinaryInteger) -> Bool let number: Int = 42 someClosure(number) // 引数の型がIntとはわからないのでエラー someClosure(.zero) // (some BinaryInteger).zeroは存在するのでエラーにならない
Avatar
Avatar
Miwa / Ensan
リバースジェネリックな引数と同じ振る舞いを持つクロージャは今のSwiftでも作ることができます let value: some BinaryInteger = 42 let someClosure = value.isMultiple // someClosure: (some BinaryInteger) -> Bool let number: Int = 42 someClosure(number) // 引数の型がIntとはわからないのでエラー someClosure(.zero) // (some BinaryInteger).zeroは存在するのでエラーにならない
これおもしろいですね。
Avatar
omochimetaru 6/30/2021 2:15 AM
(Add shared storage to property wrappers pitch on github) Introduction Property Wrappers have empowered users to abstract common property implementation details into expressive components. This proposal aims to make property wrappers more flexible and efficient by allowing them to opt-in to a shared storage. Motivation Property Wrappers are ...
2:17 AM
5日前に立ったスレッドなんだけど、Joe GroffとHolly Borla (推論器とかProperty Wrapperの機能実装してる人)とJohn McCall が長めの文章でかなりディスカッションしてる
2:18 AM
トピックとしては、Property Wrapperのメタパラメータって、値のインスタンスごとにあるのって同じ設定になってるので無駄だから、 宣言に対して一つになるように、インスタンス間で共有したほうがよいので、そういう言語機能がほしいというもの
2:20 AM
>>8 で Karl さんが ジェネリックパラメータに値が書けたらよくない?と言っていて僕もこれが綺麗だと思ったけど・・・
Avatar
今だとgenericsあるとstatic変数宣言できないってのを、何かしら制限解除すればいいんかしらね
Avatar
omochimetaru 6/30/2021 2:23 AM
このproposalでは前提としてstatic変数で宣言してそれを渡すのでも同じだけど直感的な専用記法がほしいって主張になってる。実際、この機能を使ったらコンパイル後はstatic変数になるって言ってる。
Avatar
なるほど
2:24 AM
直感的は個人の主観ではって思っちゃった
Avatar
omochimetaru 6/30/2021 2:25 AM
うん、俺は提案された仕様自体は、なんかいろいろついててわけわからんなと思った。新しいアトリビュート?キーワードが増えちゃうからね。 (edited)
Avatar
既存の仕組みで表現できるならそれの中に収める方が良いだよなぁ
2:26 AM
僕はこのDecodale Defaultをよく使うんだけど
2:26 AM
このテクニックは型パラメータとして値を入れる手法で、これでやりたいことは出来てると思う
2:27 AM
ただまあかなりテクくてわかりにくいかも。
Avatar
static変数が宣言できるようになったら、このテクが幾許か楽に書けるようになるかな?
2:28 AM
まあやるにしてもstatic解禁が良いんじゃないかなぁ
Avatar
omochimetaru 6/30/2021 2:28 AM
たるのんが言ってる解禁ってどういう話?
Avatar
@swift-5.3.3 struct Cage<Animal> { static var size=1 }
Avatar
exit status: 1 with stderr:<stdin>:2:14: error: static stored properties not supported in generic types static var size=1 ~~~~~~ ^
Avatar
これを何かしらの制約で出来るようにすると言うことです
Avatar
omochimetaru 6/30/2021 2:30 AM
それだと、 Cage 全体で共有されちゃうけど
2:30 AM
struct Hud { @Clamped(@shared: RangeStorage(0...14)) var bar = 5 @Clamped(@shared: RangeStorage(1...9)) var foo = 1 }
Avatar
例えばwhereで切るなりして宣言するとか
Avatar
omochimetaru 6/30/2021 2:31 AM
↑の すべての Hud.bar で共有、だからそこじゃないんだよね
2:31 AM
Hud 自体はジェネリックパラメータが無いから static 変数は使える。
Avatar
ンー?
Avatar
omochimetaru 6/30/2021 2:32 AM
宣言で見たユースサイト側で共有される (edited)
2:33 AM
今だと Hud のインスタンス1つにつき、bar1個と 0...14 と foo 1個と 1...9 が存在する
Avatar
何がやりたいかわかった気がするが、これは大分ややこしい機能を提案してる気がするな
Avatar
omochimetaru 6/30/2021 2:33 AM
でもどのHudのインスタンスであっても、 bar にたいして 0...14 という同じ値をもつので、それを Hudのインスタンス間で共有したい。 Clamped自体は foo では 1...9 を持つので Clamped にたいしては static ではない。 (edited)
Avatar
オブジェクトの利用宣言の側から共有変数を宣言することを強制してインスタンス化するって事ね
Avatar
omochimetaru 6/30/2021 2:35 AM
そう。
Avatar
これ共有変数が共有されるべきであるというコンテキストはどうやって指定するンや
Avatar
omochimetaru 6/30/2021 2:36 AM
@propertyWrapper struct Clamped<Value: Comparable> { @shared let storage: RangeStorage<Value> var wrappedValue: Value { ... } // a plain struct, with properties that will be shared across wrappers struct RangeStorage<Value: Comparable> { ... } }
2:36 AM
@shared っていうのが提案されてる
Avatar
sharedの宣言じゃなくて、Hud.barであるという証明が必要
2:36 AM
別にオブジェクトをinitするときに、何処で其のオブジェクトが作られたなんて今までは責務の外だったのが
Avatar
omochimetaru 6/30/2021 2:37 AM
struct Hud { @Clamped(RangeStorage(0...14)) var bar = 5 @Clamped(RangeStorage(1...9)) var foo = 1 } ↑ここで RangeStorage(0...14) を指定してるよ (edited)
Avatar
突然関係するようになってくるから死ぬんじゃないかな
Avatar
omochimetaru 6/30/2021 2:38 AM
この RangeStorage(0...14) の実行が、最初の Hud.init のときにしかされず、2回目以降はキャッシュされたオブジェクトが渡される。
2:38 AM
struct Hud { @Clamped(RangeStorage(0...14)) var bar = 5 @Clamped(RangeStorage(1...9)) var foo = 1 } var hud1 = Hud() var hud2 = Hud() // desugars to struct Hud { static let bar$shared = RangeStorage(0...14) static let foo$shared = RangeStorage(1...9) var bar = Clamped(wrappedValue: 5, @shared: bar$shared) var foo = Clamped(wrappedValue: 1, @shared: foo$shared) } // both Hud's get access to the same $shared properties. var hud1 = Hud() var hud2 = Hud() ↑のdesugars toと見比べるのが挙動は一番わかりやすいな
Avatar
ンじゃあ他のコンテキスト、例えばstruct CatでRangeStorage(1...9)って書いたらHudのsharedが汚染される?
Avatar
omochimetaru 6/30/2021 2:39 AM
いや、そのときは Cat の中に static なんちゃらが生える
Avatar
あーー、Hud側にstaticが展開されるって事ね
Avatar
またコンテキストの深い @ が増えるのか
Avatar
Miwa / Ensan 6/30/2021 2:47 AM
よくわかってないんですが、属性で@をつけるかどうかってどういう判断なんでしょう
Avatar
omochimetaru 6/30/2021 2:50 AM
@ は 追加的な型情報になってる場合 (@escaping) と、コード生成をほのめかす ( @propertyWrapper, @resultBuilder) 場合がありますね。
2:50 AM
この場合は後者のニュアンスでの採用だと思います
2:51 AM
# はコンパイルタイム変数 ( #file , #if ) のニュアンスがありますね。
Avatar
Miwa / Ensan 6/30/2021 2:51 AM
@unknownとかは後者です?
Avatar
omochimetaru 6/30/2021 2:51 AM
@unknown はどっちでもないですねw
2:52 AM
@unknown はコード検査に影響を与えるがそれ自体は制御に影響を与えないやつ。(なくてもロジックが同じ)
2:52 AM
なくてもロジックは同じで検査に影響が与えるって意味では @escaping もそうだな。
Avatar
Miwa / Ensan 6/30/2021 2:52 AM
@discardableResultとかも同じ分類ですかね、じゃあ
Avatar
omochimetaru 6/30/2021 2:53 AM
あ、そうですね。 @discardableResult はロジック一緒で検査が変わる。
Avatar
Miwa / Ensan 6/30/2021 2:53 AM
なるほど
Avatar
omochimetaru 6/30/2021 2:54 AM
その2つにわけると良さそうですね。 ロジック一緒で検査が変わるやつと、コード生成するやつ。
2:55 AM
あ、今の話は僕の持論で、公式なソースはないです。
Avatar
SE-0293とかメソッド内での宣言の場合はどうなるんだろう (edited)
Avatar
omochimetaru 6/30/2021 3:30 AM
Clampedのユースケースがまさに SE0293 なので、考慮しているんじゃないでしょうか?
3:30 AM
メソッド内のパラメータ宣言に対応して、
3:30 AM
メソッドを定義してるコンテキストにstaticに定義されれば実現はできます。
Avatar
確かにdesugarの頑張り次第ですね
Avatar
Miwa / Ensan 7/3/2021 2:56 PM
I've been talking more with @hborla and @Douglas_Gregor about this, and I think we can structure this into a series of three proposals. Expanded parameters The first proposal allows a subsequence of call arguments to be implicitly collected together at compiler time to initialize a single aggregate argument. That is, one could write a functio...
2:57 PM
expanded便利そうだなと思ったんですが、多分コード生成なので@expandedの方が近そうに見える
Avatar
norio_nomura 7/6/2021 6:46 AM
めちゃ遅いレスですが、Yamsだとomochiさんのあげたコード: func encode(to encoder: Encoder) throws { try a.encode(to: encoder) try b.encode(to: encoder) } はマージされ、 func encode(to encoder: Encoder) throws { var c = encoder.singleValueContainer() try c.encode(a) try c.encode(b) }Precondition failed:でクラッシュします。
Avatar
omochimetaru 7/6/2021 6:47 AM
家庭君のレスだとどっちも駄目だと思ったけどSVC介さない場合はオッケーだったんですね。 (edited)
Avatar
norio_nomura 7/6/2021 6:58 AM
a, bどちらもKeyedEncodingContainerを使いますが、YamsのKeyedEncodingContainercanEncodeNewValuefalseを返しても、直前に使われたのと同じ型ならば通す様になっています。UnkeyedEncodingContainerも同様。 (edited)
6:59 AM
この挙動はJSONEncoderの初期実装に合わせたような気がする。
Avatar
norio_nomura 7/6/2021 7:19 AM
KEC, UECがマージする挙動はこの辺りで初期からテストされてるけど、SingleValueEncodingContainerの挙動はテストされてないかも。 https://github.com/apple/swift-corelibs-foundation/blob/main/Tests/Foundation/Tests/TestJSONEncoder.swift#L1356-L1368
7:20 AM
あー、ランタイムクラッシュするテストを書けないから、テストで表せないのか。
😔 1
Avatar
なるほど
Avatar
@available(*, deprecated) ってProperty Wrapperには効かないんでしょうか? @available(*, deprecated) @OptionalField(key: "start_date") public var start_date: Date? があるんですが、model.start_date は警告出るのに model.$start_date は警告が出ない……
Avatar
omochimetaru 7/7/2021 2:15 AM
というか、その指定は start_date に対してついてるんじゃない?
Avatar
$start_date に対して付ける方法はないのかという疑問です。
Avatar
omochimetaru 7/7/2021 2:16 AM
なさそう projectionValue は宣言が無いから。 start_date についてるものが $start_date にも伝搬したほうが嬉しそうだな
Avatar
start_date が deprecated なのに $start_date が deprecated でない状況は存在しないように思うから、単に考慮漏れじゃないかなぁ。
2:44 AM
$ でなく _ にも出ないのか。
2:44 AM
import Combine だな・・・。本題とは関係ないけど。 (edited)
Avatar
Miwa / Ensan 7/7/2021 2:45 AM
不具合扱いでバグレポート出しちゃうのが良い気がします
Avatar
@koher シンプルで良いのでこれ参考にバグレポート書きます。
🙏 1
Avatar
import Foundation let line = (1 ... 1_000_000).map { $0.description }.joined(separator: " ") func measure(_ body: @escaping () -> Void) -> TimeInterval { let start = Date.timeIntervalSinceReferenceDate for _ in 0 ..< 10 { body() } let end = Date.timeIntervalSinceReferenceDate return (end - start) / 10 } print(measure { let numbers = line.split(separator: " ").map { Int($0)! } print(numbers.count) }, "[s]") print(measure { let numbers = line.split(separator: " ").map { Int(String($0))! } print(numbers.count) }, "[s]") (edited)
4:22 PM
$ swift -O convert-time.swift 1000000 1000000 1000000 1000000 1000000 1000000 1000000 1000000 1000000 1000000 1.265830397605896 [s] 1000000 1000000 1000000 1000000 1000000 1000000 1000000 1000000 1000000 1000000 0.3805763006210327 [s]
4:22 PM
Substring を直接 Int に変換するよりも String に変換してから Int に変換した方が速い。
4:24 PM
StringInt のイニシャライザに渡すと Int.init(_: String) が呼ばれ、 SubstringInt のイニシャライザに渡すと Int.init<S: StringProtocol>(_: S, radix: Int = 10) が呼ばれる。
4:26 PM
後者は N 進数版だから遅いのかと思ったら↓なのでそれは関係なし。 extension FixedWidthInteger { ... @inlinable @inline(__always) public init?(_ description: String) { self.init(description, radix: 10) } }
4:26 PM
Substring の場合は specialize されないから遅い?
Avatar
SIL 確認したけど Specialize されてるっぽいなぁ。単に Substring が遅いのかな・・・。
Avatar
↑これ、Substringが遅いわけじゃなくて、Stringかつメモリ上で連続アクセス可能なときfastPathに入って速くなってるんじゃないですかね? https://github.com/apple/swift/blob/2e3b1b3e77afab4d158d40f54ca8bfc76521da81/stdlib/public/core/IntegerParsing.swift#L154-L163
👀 1
1:44 AM
(というのをzennを読んで思いました https://zenn.dev/koher/articles/swift-kyopro-substring-to-int
Avatar
↑ですね。昨日 https://forums.swift.org/t/parse-int-from-substring-slower-than-string/50516/4 で同じ回答をもらいました(この問題を解決した人に)
Ah, you're using Swift 5.4! The code you're reading in IntegerParsing.swift was rewritten (by me) in March, so you'll need macOS 12/Swift 5.5 to see the results I posted. The previous implementation was indeed over 10 times slower for Substring, one of the reasons I rewrote it. My main preoccupation during the rewrite was making sure code size ...
t_naruhodo 1
Avatar
なるほど。
2:19 AM
if let str = text as? String, で分岐しちゃってるんですね。
2:20 AM
Substring でも同じ様に処理すれば同等のパフォーマンスを実現できるのか。
Avatar
Avatar
ribilynn
↑ですね。昨日 https://forums.swift.org/t/parse-int-from-substring-slower-than-string/50516/4 で同じ回答をもらいました(この問題を解決した人に)
main だとすでに解決されてるんですね。 @inlinable @inline(__always) public init?<S: StringProtocol>(_ text: S, radix: Int = 10) { _precondition(2...36 ~= radix, "Radix not in range 2...36") guard _fastPath(!text.isEmpty) else { return nil } let result: Self? = text.utf8.withContiguousStorageIfAvailable { _parseInteger(ascii: $0, radix: radix) } ?? _parseInteger(ascii: text, radix: radix) guard let result_ = result else { return nil } self = result_ }
Avatar
そうですね。原因を探そうと思ってこのコードを読んでしまって String Substring 違わないか?? と混乱しました
Avatar
後で Zenn に追記しておきます。ありがとうございました。
Avatar
違いが判らないと思ったらHEADは修正済みだったのか なるほど
Avatar
@Yuta Saito @ribilynn 追記しました。ありがとうございました。 https://zenn.dev/koher/articles/swift-kyopro-substring-to-int
👍 1
Avatar
omochimetaru 7/23/2021 7:14 AM
ええーw
Avatar
AsyncThrowingStreamはFailure==Errorのイニシャライザしかないけど特定のErrorにするにはどうしたらいいんだろ🤔
Avatar
omochimetaru 7/30/2021 7:33 AM
どちらにせよ利用側で for await in するときに型が消えるので、特定のErrorでは作れなくていいのではないでしょうか
Avatar
Failureを明示的に持たせる意味がよくわからなくて…、将来typed throwsに対応したときのためのシグネチャ的な感じなんですかね🤔
Avatar
async sequence、モナド記法もそのまま使える気配があるので、モナド記法なら型付きFailureが役に立つんだと思います
👀 1
Avatar
omochimetaru 7/30/2021 8:07 AM
AsyncStreamの方は Failure == Never になってて実装を共通化できるのかなとか思ってました
Avatar
今のところ実装は完全に別々みたいですね
Avatar
omochimetaru 7/30/2021 8:23 AM
なるほど・・・ なんかどっかのrevisionでそうなった的な話が書いてあったから、調べたら意図がわかるかな
Avatar
Kishikawa Katsumi 8/1/2021 7:30 AM
#available の否定で #unavailable が使えるようになるの便利。 新しいバージョンだと何もしなくていいけど古い場合はこれを呼ぶ必要がある、っていうのをキレイに書けなかったのがスッキリ。 https://swiftfiddle.com/udg7iynkkjebzhazpliscwovoq
7:32 AM
if !#available(...) って書けるほうがいいけど、、、って思ったことにはちゃんと説明があった。 https://github.com/apple/swift-evolution/blob/main/proposals/0290-negative-availability.md#alternatives-considered
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0290-negative-availability.md at main · apple/swift-evolution
Avatar
@availableobsoleted みたいなやつって #available にはなかったんですね。
Avatar
Avatar
Kishikawa Katsumi
if !#available(...) って書けるほうがいいけど、、、って思ったことにはちゃんと説明があった。 https://github.com/apple/swift-evolution/blob/main/proposals/0290-negative-availability.md#alternatives-considered
omochimetaru 8/1/2021 10:01 AM
ここの処理は汎用計算にはなってないっぽいですね。
Avatar
Kishikawa Katsumi 8/1/2021 10:08 AM
知らなかったわ。
Avatar
なんか、Foundation ビルドしてるときに気がついたかな。OSごとのラインタイムがあって、判断するロジックが組み込まれてたんだったかな。
Avatar
Kishikawa Katsumi 8/2/2021 4:13 PM
そうなんですね。
Avatar
clangにあるやつと同じ実装を使ってる雰囲気だった気がした
4:31 PM
嘘かも。
Avatar
omochimetaru 8/3/2021 4:48 PM
Hey folks, this pitch discusses introducing a new guard capture specifier for closure capture lists. This topic has come up before over the years ([1] [2] [3] [4] [5]), but has never been implemented before as far as I can tell (until now!). This proposal is implemented in apple/swift#38718. Introduction guard captures behave like weak captur...
4:48 PM
guard captureの提案、実装付き!
Avatar
[guard self] だと self. の省略もできるのか。なるほど〜
Avatar
実装つきすごい
5:04 PM
voidを返してるんだよなみたいなのが意味的に消滅してしまってるのが気になる
Avatar
guard の意味ぎゃくじゃねって twitter でレスされてたきがする
Avatar
早期returnを別途宣言できるようにしてさ
5:05 PM
voidならそれが省略できますってのが、丸いと思った
5:06 PM
まあでもそれだったら普通に高階util関数で良い罠
Avatar
Avatar
niw
guard の意味ぎゃくじゃねって twitter でレスされてたきがする
omochimetaru 8/3/2021 5:10 PM
スレでも[if self]を提案してる人がいますね
Avatar
なんか、if も微妙な気がするけど。
Avatar
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
ふと思ったのだけど、これasync sequenceでうっかりメモリリーク作る原因になっちゃうね
3:57 AM
// ok async { [weak self] in for await notification in NotificationCenter.default... { guard let self = self else { break } self... } } // leak! async { [weak self] in guard let self = self else { return } for await notification in NotificationCenter.default... { self... } } こういうケースは前から結構あったし、async sequenceが出てきた以上無視できないようになったと思う
Avatar
Avatar
tarunon
// ok async { [weak self] in for await notification in NotificationCenter.default... { guard let self = self else { break } self... } } // leak! async { [weak self] in guard let self = self else { return } for await notification in NotificationCenter.default... { self... } } こういうケースは前から結構あったし、async sequenceが出てきた以上無視できないようになったと思う
omochimetaru 8/11/2021 4:02 AM
あーなるほど。 for await イベント通知パターンだと、ループごとに self 取り出さないと、循環参照になるね。 [guard] captureだと固定で先頭で取り出すから駄目なのか。
4:04 AM
どうなんだろうなあ。リークというか、循環してるだけで、切ればいいよね。 画面が表示されてる間は循環してても良くて、 画面が閉じられた時にtaskを一通りcancelして購読解除してやるスタイルなら大丈夫。
Avatar
画面が表示されるたびに購読を開始して、画面が消えるたびに購読を解除するが実現可能ならそれでもいいが (edited)
Avatar
omochimetaru 8/11/2021 4:06 AM
RxSwiftだと 循環作らないようにした上で DisposeBag で全部片付けるのが主流だけど、 そもそも画面が裏に行ってるけど解放はされない状態(presentの裏とか)で、イベントが飛んできたら問題があるし。 (edited)
Avatar
viewDidUnloadがなくなって、appear系が呼ばれずにdisappear系だけが呼ばれたりする今のUIKitでその管理はかなり厳しい
Avatar
omochimetaru 8/11/2021 4:08 AM
それは左端スワイプでフェイントかけてチラチラしたりしたときに、 予告である willDisappear だけ何回も呼ばれるとかで、 didDisapperwillAppear で挟む限りは表示状態と対応取れてるんじゃなかったっけ (edited)
Avatar
interactive transitioningをキャンセルした時、遷移先でなくなった画面って、willAppearの後didDisappear呼ばれてましたっけ
4:09 AM
結構この辺は苦心した覚えがある(が、どうだったかはちゃんと覚えていない)
Avatar
omochimetaru 8/11/2021 4:10 AM
あ〜 willAppear も予告で、 didAppear が確定保証なんかな?
Avatar
あとは、willAppearから購読開始だと遅すぎるって問題があって
4:10 AM
その作りに統一しよう!っていうのは結構厳しい
Avatar
omochimetaru 8/11/2021 4:11 AM
willAppear で早めに開始したいけど willAppear だけ呼ばれて didAppeardidDisappear も呼ばれない というハマりはありそうな気がするな。
4:11 AM
でも↑で書いた、裏に居るのに NotificationCenter からイベント来たら困る問題はあるでしょ?
Avatar
まあ逆も然りだなぁ、作りによるのでは
Avatar
omochimetaru 8/11/2021 4:13 AM
interactive transitioning側のイベントをうまくハンドリングしないと、全ての問題を回避する実装ってできないんかね。
Avatar
viewController.view.windowがいるかいないかで、画面上に存在してるかどうかを見分けるのが一番楽で
4:14 AM
購読はするが、イベントを発火させるかをwindowの有無をトリガーに制御するってのが一番楽
4:14 AM
Disposeはメモリ管理に任せたい
Avatar
omochimetaru 8/11/2021 4:15 AM
view.window ってKVOできるっけ
Avatar
できない
Avatar
omochimetaru 8/11/2021 4:15 AM
じゃあcustom viewでdidMoveToWindowか
4:16 AM
presentとかpushの裏に行った時ってwindowから剥がされてるの?
Avatar
そこまで積みこんでまで[guard self]を使う理由はないなぁ
Avatar
omochimetaru 8/11/2021 4:16 AM
剥がされてない気がする。
Avatar
えーと
4:16 AM
今のpresentは裏に居続けてるから剥がれないね
Avatar
omochimetaru 8/11/2021 4:16 AM
購読はするが、イベントを発火させるかをwindowの有無をトリガーに制御する
購読はしっぱなしでイベントは読み捨てるのはなるほど。
Avatar
昔は剥がれた気がするけど、ちょっと覚えてない
Avatar
omochimetaru 8/11/2021 4:17 AM
そうだよね なんかpresentもチラ見えモードがデフォルトになったし。
4:17 AM
まあれか、さっき言った、willAppearフェイントパターンは
4:17 AM
やっぱり出なかったことはwindowチェックでいけるね。
4:18 AM
画面が出る前にはwillAppearフェイント問題があって 画面が出た後には裏画面生存問題があるんだな。
Avatar
omochimetaru 8/11/2021 4:19 AM
うーんたしかに。guard returnしたい状況のほとんどがviewControllerのselfチェックでイベント読み捨てなきはする。
4:20 AM
循環させないスタイル→先頭でespaceするのはだめ 循環させるけど切るスタイル→strong captureで良い だから
4:20 AM
まあどっちにしろ将来ほとんど出番が無い?ってことになる?
4:22 AM
I don't like this feature because I think this is an anti-pattern, but I'll toss in another spelling: guard weak self, or some other modifier on weak self. I think having the keyword weak is valuable for making the object graph ownership semantics clear; it makes it less "new syntax you have to learn the desugaring of".
4:23 AM
jroseさんがこの文法はアンチパターンを促すから良くないよって言ってて まあ unowned self 使いたいからだって意見だからぜんぜん違う視点なんだけど
4:23 AM
tarunonの書いた将来のfor awaitパターンにおいてはアンチパターンを促しそうって意見は共有する価値がありそう。
4:23 AM
アンチパターンと言うか状況によっては直接的なバグやな。
Avatar
[weak self] に限らず、 await は単発で基本的に必ず resume される想定だから strong capture でよかったという前提が、 for await によって破られてるのか。 https://discord.com/channels/291054398077927425/375206337937801216/571199858916982793 (edited)
Avatar
必ず resume される想定だから strong capture でよかったという前提が
この認識は特になかったw
4:35 AM
大半はstrongでもいいけど、気をつけないと死ぬよぐらいの温度感でした
Avatar
それが for await で普通に死ぬくらいになった感じかと。
Avatar
omochimetaru 8/11/2021 4:37 AM
そうですね。正確には無限ストリームに対するfor awaitだから問題ですね。
4:37 AM
有限ならいつか解放される。
Avatar
async { [weak self] in だとループの中で guard let self = self しやすいけど、 func foo(...) async の中で for await で無限ストリーム扱う場合とかきつくない?そんなケースはない?
4:39 AM
for await でなくても無限 for ループの中で await したら同じだけど、 for await で現実的に相当起こりやすくなってそう。
Avatar
omochimetaru 8/11/2021 4:39 AM
その場合fooが無限ストリームを返す関数になってるんじゃないかしら
Avatar
そうあるべきですねぇ
4:40 AM
書ける書けないでいうと、まあ壊すことはできます。それ言ったら func foo() { while true {} } と本質的には同じだし
Avatar
omochimetaru 8/11/2021 4:40 AM
内部で購読という副作用を起こすのは困りが増えそう
Avatar
まあ基本 async とセットで購読か。購読のメソッドだけあって呼び出す側で async する意味はないか。
4:42 AM
async { await subscribeFoo() } みたいなのはしなさそう、という意味。
Avatar
パターンとしては
4:54 AM
func subscribeFoo() { async { [weak self] in for await ... { ... } } } であるべきでしょうね
👍 1
Avatar
struct のデフォルト initializer を public にしたいだけのために init(a: ...) { self.a = a... } を大量に書かないといけないのはどうしようもないんでしたっけ。 全ての member が public であったとしても。 (edited)
Avatar
Avatar
niw
struct のデフォルト initializer を public にしたいだけのために init(a: ...) { self.a = a... } を大量に書かないといけないのはどうしようもないんでしたっけ。 全ての member が public であったとしても。 (edited)
どうしようもないと思ってますが、改善されてほしいですね。
4:36 PM
一応、型を右クリック → Show Code Actions → Generate Memberwise Initializer で生成できますが・・・。まあでも意図しない public API の破壊の可能性を考えると仕方ないのかな。
Avatar
そうかー。。。
5:01 PM
気持ちはわかる。
5:01 PM
…若干過剰なきもするけど。
Avatar
わかるけどボイラープレートだらけになるの辛いですよね・・・。
Avatar
プロポーザル出せそうなネタな気はしますね、難易度的にも丁度良い?
Avatar
ありそうではある(探してはいない) (edited)
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0018-flexible-memberwise-initialization.md at master · apple/swift-evolution
Avatar
18からのDeferredは事実上のRejectedではw (edited)
Avatar
swift の progressive exposure 的な精神で public なんてダメ絶対的なそこは譲れない一線があるのかも。
Avatar
でもenumのcaseは自由に作れちゃう
Avatar
omochimetaru 8/17/2021 3:37 AM
0018は出たのが早すぎたからで
3:37 AM
多分ちゃんと着火すれば再開するやつだと思う (edited)
3:38 AM
単に今はまだ早い的な決定がされただけで内容の議論は深まってない
3:40 AM
public struct S { public default init } とか書けたらいいと思うんですけどね
Avatar
ほしい
Avatar
これはちゃんとなにかいてみるいい機会なんだろうか...
Avatar
omochimetaru 8/19/2021 5:52 PM
The Related Projects category includes sub-categories that are dedicated to open source projects within the Swift community that are separate from the Swift language itself.
5:53 PM
5:53 PM
↑一気に5個のライブラリが1.0に向かうらしい
👀 2
Avatar
omochimetaru 8/20/2021 2:35 PM
[Announcement] Planning for Swift Collections v1.0 TLDR: We'd like to officially declare Swift Collections source stable and tag version 1.0 of it in the next week or two. Please speak up now if you have something you'd like to see changed in Deque, OrderedSet or OrderedDictionary -- this is the last opportunity to (easily) fix any API issues. ...
2:35 PM
アンスコ付きはpublicでもunstableだよって明言してる
Avatar
Hello Swift Community, As part of our efforts to improve the ergonomics of the generics system, as well as providing better support for abstractions that use tuples, I wanted to approach y’all with a sketch for the surface syntax and preliminary semantics. Because this is a large topic area with a lot of impacts on the direction of both the lan...
10:37 AM
可変長ジェネリックパラメータの設計案をcodafiさんが出した
Avatar
オッ
10:37 AM
出来るようになって欲しいねぇ
Avatar
仕様の決めが難しいよね c++みたいに型パラメータのところに任意の式が書けるようにはしたくない
10:39 AM
でも任意の式を書けるようにしないと多様なユースケースに対応できない
10:41 AM
このcodafi案で面白いと思ったのは
10:41 AM
func allPresent<T..., U...>(haystacks: T..., needles: U...) -> Bool where T == Set<U> { for (haystack, needle) in zip(haystacks, needles) { guard haystack.contains(needle) else { return false } } return true }
10:41 AM
こういうふうに、 TU の間に Constraint を書くと、
10:41 AM
T...U... の個数が同じって制約も付くらしい
Avatar
逆に違って嬉しい場面ってあったっけ、あんまり思い付かない
10:44 AM
可変長Genericsやったときって、個数がバラバラになると中のコードが異様に書きにくくなる、或いは書けるのかも怪しいと思うんですよね
Avatar
例えば、 個数の違う T...U... を受け取って、長い方のあまりをなんか別の処理に回すとか
10:45 AM
T... U... V... において T + U == V の制約のもとでペアでなにかするとか
Avatar
型のたたみ込みとそれに伴うコードの記述とか上手く行くモンなのかな
Avatar
C++ならできるね
10:46 AM
基本的に再帰的に書いて
10:46 AM
先頭一個の取り出しと、残りのリストにわけて、
Avatar
なるほどね
Avatar
ジェネリック関数自体を再帰すればなんでもできる
Avatar
async/awaitからさらに可変長Generics入ってとかなると
10:48 AM
SwiftUIはいっそ作り直した方がマトモなIF定義できるんじゃ無いかとすら思えてくる
Avatar
...はpartial rangeに使っちゃったからsplatに使えないのかw
Avatar
for-inの中で要素の型がイテレーションごとに変わるけど、全ての要素に対して同じ制約を課すことで、ループ内の型検査が静的にできるようになってるのが良い
11:21 AM
前おもちさんと話したのを掘り起こした https://twitter.com/kateinoigakukun/status/1220591042228940802?s=21
@omochimetaru あー、それでいうと気になってたのは文法とランタイムの話かもしれないです 型の数はcalleeを定義するときに決定できないからイテレートする手段が提供されないといけないけど、そうするとfor param in paramsでparamの型が毎回変わるのか。とか
👀 1
Avatar
この提案だと
11:52 AM
struct Head<H, R...> { } func car<T...>(_ t: T...) -> Head<T...>.H { t[0] }
11:53 AM
これできるのかな T... が 0個のときおかしいから駄目かな
Avatar
C++っぽい
Avatar
例えば高階関数を畳み込むようなやつがこういうのができないと書けないよねえ
11:55 AM
forループに書き下して無理やりやれるかもしれんけども、、、
Avatar
具体的なユースケースどんなのあります?
Avatar
レス13に稲見さんの書き込みあった
Avatar
Avatar
Yuta Saito
具体的なユースケースどんなのあります?
最近まさに使ってるのだと、 EventLoopFutureを返す関数をN個受け取って、 順番にflatMapで呼び出して、 N要素のタプルのELFを返す高階関数を6通りオーバーロードした (edited)
Avatar
なるほどそれは無理そう
Avatar
Introduce an additional build product to build-script to build back-deployable concurrency libraries. These libraries would need to be embedded in apps deployed prior to macOS 12/iOS 15 to support ...
Avatar
Kishikawa Katsumi 8/27/2021 2:28 AM
やったー
2:29 AM
These libraries would need to be embedded in apps deployed prior to macOS 12/iOS 15 to support concurrency.
Avatar
今後こういう機能が追加されてもBack deployされることがわかってうれしい
Avatar
これどうやってEmbeddedされるんだろう
Avatar
Back deploy用のlibswift_Concurrency.dylibがアプリに埋め込まれるんじゃ無いんですかね
2:44 AM
ビルドシステムが頑張る
Avatar
Build Settingsにフラグが生えるのか (edited)
Avatar
Kishikawa Katsumi 8/27/2021 2:46 AM
バックポートできるのはiOS 13までっぽいね。13でも使えるっていうのはかなり大きいんじゃないだろうか。
👉 1
Avatar
Always Embed Standard Libraryみたいなオプションが生えそう
Avatar
もうありそうな名前だw
Avatar
ABI Stableなランタイムが出荷されたのが13でしたっけ
Avatar
Kishikawa Katsumi 8/27/2021 2:48 AM
おお、そういうことか。12以前は手の出しようがないのか。
Avatar
そんな気がしますねえ
Avatar
15が出れば底が13でも大きな問題は無いだろうし、時間で解決できそう
Avatar
今もう大体12は切られてるはず。大きな会社は知らんけど
Avatar
omochimetaru 8/27/2021 3:17 AM
iOSで早めに使えるようになったか やったー
Avatar
Avatar
Yuta Saito
ABI Stableなランタイムが出荷されたのが13でしたっけ
omochimetaru 8/27/2021 3:18 AM
Concurrency.dylibが libSwiftCore.dylibiOS13, 14, 15 同梱版全部とリンクできるようになっとるってことか (edited)
3:19 AM
iOS12はABI Stableじゃないからリンクできない可能性があると
3:19 AM
stdlibのABI stabilityなんも気にしてなかったけどこういう影響があるのか
Avatar
上に貼ってたPRの他に準備のためのPRがいくつかあるように見えたので追ってみるか
3:24 AM
古いランタイム向けのバックデプロイパッチがあるお陰でConcurrencyライブラリはランタイムのバージョンごとに手を入れる必要が無いのかな
Avatar
omochimetaru 8/27/2021 3:26 AM
バックデプロイパッチは、新しく増えた関数は使えないけど、既存関数で挙動が変わったものを新しい挙動にパッチするから、 古い関数(ただし新しい挙動)だけで作れば同じ
3:26 AM
でもそれはランタイム関数だけで、
3:26 AM
標準ライブラリ部分はパッチの仕組みないから
3:26 AM
標準ライブラリは気をつけてソース固定してるんだよね?
Avatar
あー、そうですね
3:27 AM
今回のConcurrencyモジュールはモジュールを分けてたおかげですんなり行けた
Avatar
omochimetaru 8/27/2021 3:28 AM
だから実行時に動くコードは ・1. Swiftで書かれたstdlibライブラリ実装 ・2. ランタイム関数部分 ・3. ユーザーがビルドしてコード生成された部分 の3種類あって、1と2は環境固定だけど2だけは一部パッチできる
3:29 AM
コンパイラチームはあらゆる仕組みを1と2と3のどれにするか気をつけて設計しないといけない
3:29 AM
(原理的に選択肢1がほぼだめな場合はあるけど
3:29 AM
何を2にするかはかなり難しそうだけど経験と勘でうまいことやっているんかな
Avatar
そして1の実装詳細をうっかりinlinableとかでABI Publicにすると一生固定することになる
Avatar
omochimetaru 8/27/2021 3:30 AM
それはどうなんだろう?
3:30 AM
結果が同じなら実装コードは変わってても問題なくない?
3:31 AM
動かす時に、アプリの中にインライン埋め込みされたコードと、環境のライブラリを呼出すコードが混在するけど
Avatar
変えられるコードの範囲が限定されないですか?
Avatar
omochimetaru 8/27/2021 3:31 AM
その結果のデータの変化が同じ挙動なら大丈夫
Avatar
ミクロな単位ではそう
Avatar
omochimetaru 8/27/2021 3:32 AM
そもそも「仕様」はABIprivateであっても変えちゃいけないから
3:32 AM
結構大丈夫な気がするんだよね
3:33 AM
データ構造は固定しがちだからそこが一番厳しそう
3:33 AM
まあでも大丈夫かどうかを人間が気にするのが複雑すぎて無理そうではあるな
Avatar
コアチームのレビューが砦
3:35 AM
そういえば、KeyPathのランタイム実装が、2にあっても良さそうだけど何故か1にあるんですよね
Avatar
SwiftとしてはConcurrencyが使えるけど、例えばSwiftUIのasyncなAPIを古いOS向けに出すのってきっと難しいんだよね?
Avatar
Avatar
Yuta Saito
そういえば、KeyPathのランタイム実装が、2にあっても良さそうだけど何故か1にあるんですよね
omochimetaru 8/27/2021 3:36 AM
Swiftで実装されているけど他のランタイム関数と同じでパッチ可能なテーブルに乗ってない?
Avatar
Avatar
omochimetaru
Swiftで実装されているけど他のランタイム関数と同じでパッチ可能なテーブルに乗ってない?
あーどうだろう。実はRuntimrFunction.defに入ってたりするのかな
Avatar
Avatar
d_date
SwiftとしてはConcurrencyが使えるけど、例えばSwiftUIのasyncなAPIを古いOS向けに出すのってきっと難しいんだよね?
一つのモジュールに新しいAPIを足すのは難しそうですねぇ
3:39 AM
ObjCヘッダから自動変換するやつは使えそう
Avatar
だよねぇ
Avatar
omochimetaru 8/27/2021 3:42 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
3:42 AM
@Yuta Saito swift_geyKeyPath あったよ
Avatar
それだ。じゃあ一応差し替えられるんですね
Avatar
omochimetaru 8/27/2021 3:42 AM
これSwift側でもこの名前になるように silgen_name かなんかついてなかったっけ
3:42 AM
むしろ昔家庭くんに教えてもらった気がするんだよな
3:43 AM
なので1と2の違いは実装言語は実は関係なくて(混ぜてリンクされるし) 単に RuntimeFunctions.def に掲載されるかどうかという事かな
Avatar
そうそう。ランタイム関数の宣言はC呼び出し規約なのにsilgen_nameで実装してるからswiftccになってて規約違反してた
Avatar
Avatar
omochimetaru
なので1と2の違いは実装言語は実は関係なくて(混ぜてリンクされるし) 単に RuntimeFunctions.def に掲載されるかどうかという事かな
ですね
Avatar
Avatar
Yuta Saito
そうそう。ランタイム関数の宣言はC呼び出し規約なのにsilgen_nameで実装してるからswiftccになってて規約違反してた
omochimetaru 8/27/2021 3:44 AM
あ〜 calling convention 関係か
3:44 AM
まあ ランタイム関数テーブルを経由するとオーバーヘッドもかかるし最適化阻害もあるから
3:45 AM
何を割り当てるかはやっぱり難しそう。
Avatar
デザインセンスが問われる
Avatar
APIデザインむづい
Avatar
omochimetaru 8/27/2021 8:45 AM
@Yuta Saito そういえば、stdlibのフックの仕組みはもっと前からあったけど、iOS13からのABI stableって何を意味してるの?
8:45 AM
ABI stableでないころに、フックが有効に機能するシナリオがよくわからない
Avatar
ん、質問が難しい
Avatar
omochimetaru 8/27/2021 8:51 AM
えーっと
8:51 AM
stdlib hookの仕組みってそもそも、
8:51 AM
新しいSwiftでアプリをビルドした時に、実行環境のSwift Stdlibが古い時に、
8:51 AM
起動時にフックをロードして、実行環境のSwift Stdlibの挙動を新しいSwiftに合わせる仕組みでしょ?
Avatar
はい
Avatar
omochimetaru 8/27/2021 8:52 AM
それが動作するって前提条件だったら、それってABI Stableとは違うのか?ってこと
8:52 AM
例えばもし、フックとは関係ない標準ライブラリの関数の仕様が変わってしまっているなら
8:53 AM
そもそもフック以前に、その部分の影響で動かせない
8:53 AM
フックが機能するってことは、フックできない部分も、古いstdlibバイナリが、新しいアプリと動的リンクできないとおかしい
Avatar
フックの仕組みは5.0から入った機能じゃなかったでしたっけ
Avatar
omochimetaru 8/27/2021 9:02 AM
そうだと思う。あれ?iOS13が5.0?
Avatar
そうそう
Avatar
omochimetaru 8/27/2021 9:02 AM
えっ
9:02 AM
iOS13ってすごい最近だけどSwift5って大昔じゃないっけ
Avatar
Swift 5.0 は iOS 12から?
Avatar
嘘だった
9:03 AM
じゃあ5.1でABI Stableかな
9:04 AM
どっちだっけ
Avatar
omochimetaru 8/27/2021 9:04 AM
hookの仕組みって __50 とかなかったっけ
Avatar
Compatibility50があった
Avatar
omochimetaru 8/27/2021 9:04 AM
それそれ。
9:04 AM
Compatibility50があるiOS12でもいけそうな気がする
Avatar
OSに入ってるんだっけ
Avatar
Swift 5.1 は Module Stability らしい https://swift.org/blog/5-1-release-process/
This post describes the goals, release process, and estimated schedule for Swift 5.1.
Avatar
omochimetaru 8/27/2021 9:05 AM
5.1のmodule stabilityは人々が使えるようになったやつで
9:06 AM
5.0のstdlibは先行して特別にstableじゃなかったっけ
9:06 AM
Dispatchとかにも依存しててそっちが駄目とかあるのかな
Avatar
Build a static archive that can be linked into executables and take advantage of the Swift runtime&#39;s hooking mechanism to work around the issue Doug fixed in #24759. The Swift 5.0 version o...
Avatar
omochimetaru 8/27/2021 9:18 AM
なんか俺がいる
Avatar
いた
Avatar
omochimetaru 8/27/2021 9:20 AM
swift_conformsToProtocol を Swift5.0 向けにパッチを同梱出荷するようにした修正
Avatar
じゃあ4.2のランタイムにくっつけるってことか?
Avatar
omochimetaru 8/27/2021 9:21 AM
これはcompat50だから、既に出荷した5.0ランタイムを
9:21 AM
swift5.1でビルドしたアプリを動かすために差し替える話じゃない?
Avatar
ん、それはCompat51じゃないですかね
Avatar
Avatar
omochimetaru
swift5.1でビルドしたアプリを動かすために差し替える話じゃない?
あ、逆か。これであってるのか。
9:26 AM
すみません
9:28 AM
Swift apps no longer include dynamically linked libraries for the Swift standard library and Swift SDK overlays in build variants for devices running iOS 12.2, watchOS 5.2, and tvOS 12.2.
https://developer.apple.com/documentation/xcode-release-notes/swift-5-release-notes-for-xcode-10_2 iOS 12.2から一応ランタイムはOSに入ってるっぽい
Avatar
omochimetaru 8/27/2021 9:29 AM
なるほど
9:29 AM
マイナーバージョンだからまあ13.0からって感じかな
Avatar
Swiftにはランタイム関数を差し替える機能がある。 これにより、新しいコンパイラでビルドした実行ファイルを、 古いマシン環境で実行した場合でも、 そのマシンに同根されている古いランタイムの挙動を新しいものに変える事で、 実行ファイルの後方互換性をABIレベルで実現している。 この差し替え関数は__swift51_hooksというセクションに登録されていて、 実行時にロードされる。 このあた...
5:58 PM
これ?
Avatar
omochimetaru 8/27/2021 9:07 PM
それ
Avatar
https://iosdiscord.connpass.com/event/223396 今回のback deployment関連の話、今度わいわいswiftcでやることになったのでどうぞ~
# わいわいswiftc #30 オンライン 昨今の社会的情勢を鑑みて、当面はオンライン開催を致します。 swift-developers-japanのDiscordサーバー上でオンライン配信を行う予定です。 Discordサーバーへはこちらのリンクから参加いただけます。 https://discord.gg/7RKD8dxBsm 本サーバーについて詳しく知りたい方は、下記をご覧ください。 https://medium.com/swift-column/discord-ios-20d586e373c0 # わいわいswiftc わいわいswiftcは、Swift Comp...
👏 4
Avatar
Concurrencyのback deployment、デフォで有効になったのか https://github.com/apple/swift/pull/39090
Remove the option that explicitly enables concurrency back-deployment, and instead always enable its support in the compiler. Remove the use of the extraneous CMake option as well.
🎉 2
Avatar
Hello everyone, With the recent introduction of Swift concurrency, and most notably actors to the language, Swift gained powerful and foundational building blocks for expressing thread-safe concurrent programs. This proposal aims to extend Swift's actors with the ability to work equally well for distributed systems thanks to the introduction of...
Distributed actors transport example, for feature review - GitHub - apple/swift-sample-distributed-actors-transport: Distributed actors transport example, for feature review
Avatar
omochimetaru 9/1/2021 5:29 PM
少しずつ読んでる
Avatar
omochimetaru 9/2/2021 2:11 AM
distributed actor の distributed func は、 actor の func が isolated な呼び出しのときに必ず async になるように、 isolated な呼び出しが必ず async throws になる事によって、 通信が失敗する(ネットワークトラブル、リモートホストのクラッシュ)などの場合にエラーが飛ぶらしい。アクターじゃん。
2:12 AM
そして、distributed func の 引数と返り値は、 Sendable である事に加えて、 Codable である事を要求されるらしい。良さそう。
Avatar
想像してた感じになってて良い
2:13 AM
Akkaじゃん
Avatar
omochimetaru 9/2/2021 2:14 AM
ActorTransportの実装では、リモートホストにあるActorインスタンスのメソッドを呼出す場合のための実装として、 _receive_xxx という特別な名前のメソッドを @dynamicReplacement(for:) で注入するとかなんとか書いてあるんだけど、なんでそんなややこしい話になってるのかうまく読み解けなかった。
2:14 AM
また後日続きを読みます。
Avatar
Avatar
Yuta Saito
想像してた感じになってて良い
omochimetaru 9/2/2021 2:15 AM
うむ。基本的な仕組みは、できそうだな〜と思ってたやつがそのまんま綺麗に実現できるってぽい。すごい。
Avatar
さすがKonradさん
Avatar
omochimetaru 9/2/2021 2:18 AM
ネットワークアプリやマルチプロセスアプリを作る時に、自分でソケットやプロトコルを実装しなくても
2:18 AM
このアクター仕様の上に組めばかなり楽ができそうと感じた
2:19 AM
アクターを使うというより、アクターをプロトコルライブラリとして使えそう
Avatar
Avatar
omochimetaru
distributed actor の distributed func は、 actor の func が isolated な呼び出しのときに必ず async になるように、 isolated な呼び出しが必ず async throws になる事によって、 通信が失敗する(ネットワークトラブル、リモートホストのクラッシュ)などの場合にエラーが飛ぶらしい。アクターじゃん。
Erlang の actor っぽい。
Avatar
omochimetaru 9/2/2021 2:55 AM
ですよね。
2:55 AM
2017年?のラトナードラフトがほぼそのまんま実現されていて
2:56 AM
Konradさんがこのために呼ばれた感がめっちゃする
Avatar
omochimetaru 9/6/2021 1:48 AM
長かったけど読み終わった
1:49 AM
distributed func は、ビルドすると ローカル/リモート分岐するthunkにラップされて、実装したコードはローカル版の実装になり
1:49 AM
リモート版は _remote_<method name> というクラッシュするだけの関数になっていて (edited)
1:50 AM
これを dynamicReplacement で実装を入れ込むそうな
1:51 AM
ActorTransportライブラリが、SwiftPMのextension packageを使って、コード生成を行う事を想定していて
1:51 AM
これによって、distributedメソッドごとに、メッセージ生成と送信の処理を生成する
1:52 AM
なかなか派手な仕様だけど、
1:52 AM
たしかにSwiftの言語機能だと、メソッド呼び出しそれ自体を抽象化してフックする一級の仕組みは無いから
1:53 AM
とりあえずそうなったっぽい
Avatar
なるほど。派手だ
Avatar
omochimetaru 9/6/2021 2:03 AM
提案読み終わったころにはフォーラムが伸びてた まだ少ししか見てないけど、Codableは遅いから微妙じゃない?って意見が気になった
Avatar
Codable遅いんですか
Avatar
omochimetaru 9/6/2021 2:05 AM
まあ俺も遅いなーとは思ってる
2:07 AM
プロトコル呼び出しが多すぎてディスパッチオーバーヘッドが大きい感じがしてる
2:08 AM
サーバーサイド(vapor)で使っててもCodableの処理時間がちょっと多くてしぶい
Avatar
エンコーダ/デコーダの問題なのかCodable自体の生成コードの問題なのか調べたいですね
Avatar
omochimetaru 9/6/2021 2:11 AM
そうね。本質的な問題がどこなのかはっきりわかっていない。
Avatar
なんか昔測ったときはJSONSerializationのほうが2倍以上速かったですね
Avatar
omochimetaru 9/6/2021 2:40 AM
JSONSerializationは超早いんすよね。 JSONDecoder使うと 文字列→JSON→SwiftType の 2段階の変換になっているけど、後段で前段の5倍ぐらい時間がかかるイメージ
Avatar
JSONSerialization (というか NSJSONSerialization )は NSDictionary とか NSArray 使うけど、最初から Swift ネイティブな DictionaryArray を使ってくれたらもっと速くなりそう。今、遅い原因で支配的なのは Codable の方だろうけど。
Avatar
omochimetaru 9/6/2021 2:47 AM
The Foundation Project, providing core utilities, internationalization, and OS independence - swift-corelibs-foundation/NSArray.swift at main · apple/swift-corelibs-foundation
2:48 AM
気になって見てみたらlinuxだとNSArrayがArray<AnyObject>で実装されてるんだな
Avatar
NSNumber とかでボクシングされるのも辛い。
Avatar
omochimetaru 9/6/2021 3:15 AM
nsnumberは小さい整数ならtagged pointerになるからヒープ確保はしないですけどね
3:16 AM
余計なオーバーヘッドはありますね
Avatar
Avatar
omochimetaru
nsnumberは小さい整数ならtagged pointerになるからヒープ確保はしないですけどね
そうなんだ。これは知らなかった。
Avatar
omochimetaru 9/7/2021 2:18 AM
distributed actorのフォーラム書き込みを読んだ
2:19 AM
Douglasさんのツッコミで
2:20 AM
distributed func 指定子いらなくない?というのが一番おもしろかった
2:21 AM
Actorのメソッドはアクターの外からasyncとして呼べるように Distributed Actorのメソッドはasync throwsとして呼べるでいいじゃんと
2:21 AM
protocolの distributed func エントリもなくして、 async throws なら呼べるで良い
Avatar
読んでないけど、 async throws に加えて Distributed Actor のメソッドに渡せる/返せるものは Sendable の代わりに Codable という制約があればいいのかな?参照型でもコピーになるし。 Codable は理想的な実装になったとしても無駄が多そうだから(キーを焼き込まないといけないので)、 Serializable みたいなものがあった方が良さそう?
Avatar
CodableでもUnkeyedコンテナ使えば無駄なくできそうだなと思いましたが、デフォルト実装が無いのが辛いですね
Avatar
Avatar
koher
読んでないけど、 async throws に加えて Distributed Actor のメソッドに渡せる/返せるものは Sendable の代わりに Codable という制約があればいいのかな?参照型でもコピーになるし。 Codable は理想的な実装になったとしても無駄が多そうだから(キーを焼き込まないといけないので)、 Serializable みたいなものがあった方が良さそう?
omochimetaru 9/9/2021 1:38 AM
提案はそうなってますね
1:38 AM
ドーグさんが、プロトコルはCodableだと広すぎるからトランスポート側で指定できる方がいいんちゃうって指摘していて
1:39 AM
コンラッドさんが、Codableは楽ちんなデフォルトだといいんじゃないか、とか言ってた
Avatar
Avatar
Yuta Saito
CodableでもUnkeyedコンテナ使えば無駄なくできそうだなと思いましたが、デフォルト実装が無いのが辛いですね
なるほど、たしかに。 Serializable でもデフォルト実装ないと辛いですね。
1:44 AM
UnkeyedEncodingContainer って JSON にしたらどうなるのかよくわかってなかったけど↓こうなるのか。 @swift-5.4.3 import Foundation struct Foo { var a: Int var b: String var c: Bool } extension Foo: Encodable { func encode(to encoder: Encoder) throws { var container = encoder.unkeyedContainer() try container.encode(a) try container.encode(b) try container.encode(c) } } let original: Foo = .init(a: 42, b: "xyz", c: true) let encoded = try! JSONEncoder().encode(original) print(String(data: encoded, encoding: .utf8)!)
Avatar
swift54 BOT 9/9/2021 1:44 AM
[42,"xyz",true]
Avatar
omochimetaru 9/9/2021 1:45 AM
そうですよ 上方互換性が取りにくい
Avatar
Unkeyed でなくても SerializationEncoder みたいなのを作るときに、キーをソートしてからバイト列に変換するとかすればキーは省略できるかな?スキップされたOptionalなキーはスキップの印だけ入れて。
Avatar
omochimetaru 9/9/2021 1:50 AM
新しいバージョンでフィールドが増えているときに、古いペイロードパケットが読めなくなります
1:50 AM
Distributed Actorを使う状況で、全てのノードが同時に最新版をデプロイできるものなのかどうか。
1:51 AM
暗号通貨ネットワークみたいな分散P2Pシステムを作るんだったら、
1:51 AM
ノードごとにバイナリバージョンがズレてることはあるのかも
1:51 AM
対戦ゲームみたいなアプリだったら、揃ってそうだからそういう方法もありですね
Avatar
新しいバージョンでフィールドが増えているときに、古いペイロードパケットが読めなくなります
これは思ったんだけど、結局リネームされたとかだと対応できないわけだし程度問題かなと。 で、
全てのノードが同時に最新版をデプロイできる
を前提とする(か、フォーマットが変わらない範囲のアップデートのみ許容する)のは仕方ないのかなぁと。
Avatar
omochimetaru 9/9/2021 1:55 AM
一般系には対応できないですが追加だけなら大丈夫なので人間が意識するやつですね。(もしくは、機械的にチェックするか
1:55 AM
Unkeyedでも、末尾への追加しかしなければ追加はできます。
1:55 AM
「キーでソートする」があると追加位置が名前次第で真ん中になるのでindexがズレちゃう。 (edited)
Avatar
Codable 限定だと JSON には Keyed で書き出したいけど Distributed Actor でやり取りする場合には Unkeyed で最適化したいみたいなのができないから辛いかなと思ったけどどうだろう?シリアライズするエンコーダががんばるにしても、 distributed なコンテクストにエンコーダ指定できるとかないければ、結局エンコーダをどう実装するか(キーを残すのか残さないのか)の二者択一になって、
暗号通貨ネットワークみたいな分散P2Pシステムを作るんだったら、ノードごとにバイナリバージョンがズレてることはあるのかも
対戦ゲームみたいなアプリだったら、揃ってそう
の両者に最適化できない。
Avatar
omochimetaru 9/9/2021 2:00 AM
ああなるほど
Avatar
それでいうと Codable もすでに破綻してるのかな?サーバーAにはA用のフォーマットで、サーバーBにはB用のフォーマットでエンコード/デコードしたいとかはできないわけだし、やり取り用の専用の型を間に噛ますしかない。 (edited)
Avatar
omochimetaru 9/9/2021 2:01 AM
Unkeyedだと自動生成もなくてしんどいからEncoder側でキーを消すということか (edited)
Avatar
Avatar
omochimetaru
Unkeyedだと自動生成もなくてしんどいからEncoder側でキーを消すということか (edited)
そうそう。でもやりとりするサイズは小さくできるけど、エンコード/デコードがますます遅くなりそう。
Avatar
omochimetaru 9/9/2021 2:02 AM
distributed なコンテクストにエンコーダ指定できるとかないければ
Actor Transportオブジェクトがシリアライズは全責任を持つので、Codable依存は無いですね
2:02 AM
そういえばそこちょっと変だな
2:03 AM
Codableを実際に使用するかどうかはActorTransport実装依存なのに、言語としてはCodableであることを常にチェックするのか
Avatar
Avatar
omochimetaru
distributed なコンテクストにエンコーダ指定できるとかないければ
Actor Transportオブジェクトがシリアライズは全責任を持つので、Codable依存は無いですね
なるほど。そろそろ想像してる内容と現実がずれてきてそうだから、ちゃんと読んでから話します。
👀 1
Avatar
omochimetaru 9/9/2021 2:10 AM
僕も提案とフォーラムは目を通したから後はサンプル実装を読まなきゃ。
Avatar
omochimetaru 9/13/2021 5:44 AM
アプリケーションの方のサンプル実装のトランスポート生成器の実装は、 (edited)
5:44 AM
ソースコードと完全に対応した手動定義された生成結果を埋め込んでるだけの嘘だった
Avatar
w
5:45 AM
やればできる。あとはやるだけ (edited)
Avatar
omochimetaru 9/13/2021 5:46 AM
Fishy: 怪しい、いかがわしい、うさんくさい、魚の、魚の多い、魚からなる、魚のような、生臭い、どんよりした、無表情の ↑調べて納得した
Avatar
そういことか
Avatar
omochimetaru 9/13/2021 5:50 AM
まあ、実際に生成されてるのはどういうコードなのかが、テキストとして見られる状態のほうが、仕様を理解する上では助かるね。
Avatar
Introduction When error handling was added to Swift in 2015, it intentionally did not allow the expression of precise error types: either a function cannot throw, or it can throw any Error. The error-handling rationale I wrote, which uses an awful lot of words to describe most aspects of the design, gives this one pretty short shrift: There ar...
11:11 AM
エラーの型についての議論が投稿された
Avatar
やっぱUnion型に踏み込まないといけないよね
Avatar
まだ読んでない
Avatar
真ん中ぐらいにType combinatorsで議論がある typed Errorの実装はuntaggedなUnion型とのセットだから、やっぱハードルがクソ高いよなと思う
Avatar
読んだけど、John McCallさんの英語はやはり難しい・・・
12:34 PM
ローレベルなライブラリで、パフォーマンスと正確性のために使いたい場合と、 ジェネリクスと組み合わせたいケースのために必要だから機能は足すべきだけど、 一般的なコードではやらないほうが良い、 解決する問題より、複雑になって持ち込まれる問題のほうが多い、 というような意見に見えた
12:34 PM
errorUnionの議論のくだりは結局これをやるべきと言ってるのかやらんべきと言ってるのかわからず。
12:35 PM
下層のエラーを合成するようなケースは Swift.Error にアップキャストしてまとめちゃうのが良いと言っている・・・?
Avatar
ローレベルなライブラリで、パフォーマンスと正確性のために使いたい場合
今は全部 Existential だからパフォーマンス悪いのか。
Avatar
omochimetaru 9/14/2021 3:56 PM
そうですね。ダブルポインタにlowerされてる(しかも専用レジスタに割り当てられる)から、ダイナミックアロケーションは無いんだけど、それでもオーバーヘッドはあるみたいな事が書いてあるような・・・
Avatar
まだdraftですが...back deploymentのrelease/5.5へのPRが出てますね https://github.com/apple/swift/pull/39342 (edited)
Avatar
おー
Avatar
👀 1
12:50 PM
なんかややこしそうな事もしてる (edited)
Avatar
うわぁそうしたか
Avatar
どういうこと?
Avatar
ウィークリンク
Avatar
weak_import
Avatar
本物のランタイムがある時にシンボルがコンフリクトするのを回避するためのハック
Avatar
omochimetaru 9/17/2021 1:00 PM
ふむふむ
Avatar
あいや、weak_importは元々あったやつか
1:03 PM
別ファイルから移動してきただけっぽい
1:09 PM
詳しいことは来週の金曜日までにまとめよう…
👀 4
Avatar
まとめに期待
Avatar
やばいそのbackdeployの話がすごい気になって今度のわいわい参加しようと思ったら、見事にメルカリさんのiOSDCアフターイベントとかぶってしまった 😇 どうしよう
Avatar
さっきkoherさんのAsk the speakerの時に話に出ていたResultinit async、こんな感じですかね?🤔 https://forums.swift.org/t/swift-concurrency-feedback-wanted/49336/105 (edited)
Result could be extended with an async initialiser — something like this: extension Result where Failure == Error { init(awaiting task: () async throws -> Success) async { do { self = .success(try await task()) } catch { self = .failure(error) } } } self.taskHandle = async { self.result = await Result { try aw...
👀 2
Avatar
Avatar
lovee
やばいそのbackdeployの話がすごい気になって今度のわいわい参加しようと思ったら、見事にメルカリさんのiOSDCアフターイベントとかぶってしまった 😇 どうしよう
ワイワイは録画もあるよ
😻 1
Avatar
Avatar
shiz
さっきkoherさんのAsk the speakerの時に話に出ていたResultinit async、こんな感じですかね?🤔 https://forums.swift.org/t/swift-concurrency-feedback-wanted/49336/105 (edited)
まさにそれですね
👍🏻 1
Avatar
どこかで見たなーと思い気になって探しましたw (edited)
Avatar
@swift-5.5.3 import Foundation class C {} _ = AsyncStream(String.self) { continuation in let c = C() continuation.onTermination = { print("\(c)") } } _ = AsyncStream(String.self) { continuation in let c = C() let cushion: @Sendable (AsyncStream<String>.Continuation.Termination) -> Void = { _ in print("\(c)") } continuation.onTermination = cushion } (edited)
Avatar
Avatar
Iceman
@swift-5.5.3 import Foundation class C {} _ = AsyncStream(String.self) { continuation in let c = C() continuation.onTermination = { print("\(c)") } } _ = AsyncStream(String.self) { continuation in let c = C() let cushion: @Sendable (AsyncStream<String>.Continuation.Termination) -> Void = { _ in print("\(c)") } continuation.onTermination = cushion } (edited)
exit status: 1 with stderr:<stdin>:7:30: error: converting non-concurrent function value to '@Sendable (AsyncStream<String>.Continuation.Termination) -> Void' may introduce data races continuation.onTermination = { ^ (edited)
Avatar
Avatar
swift55
exit status: 1 with stderr:<stdin>:7:30: error: converting non-concurrent function value to '@Sendable (AsyncStream<String>.Continuation.Termination) -> Void' may introduce data races continuation.onTermination = { ^ (edited)
onTermination に差し込むクロージャが Sendableにならないっぽくて困ってるのですが何かわかるかたいますか? クッション挟むといけてて謎。(しかもc はsendableじゃないし)
Avatar
Swift 5.5 is now officially released! Swift 5.5 is a massive release, which includes newly introduced language capabilities for concurrency, including async/await, structured concurrency, and Actors. My heartfelt thanks to the entire Swift community for all the active discussion, review, and iteration on the concurrency (and other additions) t...
👏🏻 1
Avatar
Avatar
Iceman
onTermination に差し込むクロージャが Sendableにならないっぽくて困ってるのですが何かわかるかたいますか? クッション挟むといけてて謎。(しかもc はsendableじゃないし)
continuation.onTermination = { @Sendable _ inでどうでしょうか?
(しかもc はsendableじゃないし)
以前mainに追加されたSendableチェックがrelease/5.5にまだ入ってないんですよね。mainでやるとwarningが出ます(5.5に入らないんですかね?)🤔
(edited)
Avatar
Avatar
shiz
continuation.onTermination = { @Sendable _ inでどうでしょうか?
(しかもc はsendableじゃないし)
以前mainに追加されたSendableチェックがrelease/5.5にまだ入ってないんですよね。mainでやるとwarningが出ます(5.5に入らないんですかね?)🤔
(edited)
お〜これでいけました!ここに @Sendable つけるんですね😅
5:48 AM
Sendableチェックはまだ全部じゃなかったんですね
Avatar
Avatar
Iceman
お〜これでいけました!ここに @Sendable つけるんですね😅
以前同じところでハマって↓を見て「そうなんだ」って思ったことを思い出しましたw https://forums.swift.org/t/asyncstream-and-progress-reporting/50588/7 Sendableチェックは↓に向けて色々変わっているみたいですね。そしてプロポーザル通りにチェックされないところもあって僕もまだよくわかってない状態です😅 https://forums.swift.org/t/pitch-staging-in-sendable-checking/51341
I get it now. The onTermination closure needs to be annotated with @Sendable: continuation.onTermination = { @Sendable termination in … }
Hi all! SE-0302 introduced the Sendable protocol, which is used to indicate which types have values that can safely be copied across actors or, more generally, into any context where a copy of the value might be used concurrently with the original. Applied uniformly to all Swift code, Sendable checking eliminates a large class of data races cau...
Avatar
Task 作ったときにactorが引き継がれるのってどういう条件なんですか。async/await 外のコールバックの中で Task 作っても引き継がれるとは思ってなかった 😲 https://zenn.dev/link/comments/6d69e9523300b4
Avatar
外側がアクター世界だと引き継がれますね 大半はMainActorなんじゃないだろうか
Avatar
WWDCのセッションに何が引き継がれるかのチートシートがあったはず
1:34 AM
どれだっけな
1:36 AM
あった。Joe Groff先生が教えてくれるやつ https://developer.apple.com/videos/play/wwdc2021/10134/
When you have code that needs to run at the same time as other code, it's important to choose the right tool for the job. We'll take you...
👍 1
1:37 AM
26分くらいのところに多分知りたいスライドがあります
🙇 1
Avatar
YouTube みたいにタイムスタンプでリンクできたらいいのにな (edited)
Avatar
きっとフルで見てもらうためにわざと…🙃
🙄 2
Avatar
Avatar
Yuta Saito
26分くらいのところに多分知りたいスライドがあります
おお!見てみます!ありがとうございます!これみてなかった(みてないのいろいろある)
👍 1
1:50 AM
いや、これは見たことあるなw
Avatar
Avatar
hironytic
Task 作ったときにactorが引き継がれるのってどういう条件なんですか。async/await 外のコールバックの中で Task 作っても引き継がれるとは思ってなかった 😲 https://zenn.dev/link/comments/6d69e9523300b4
tarunon さんの言うように、外側が actor の世界だとその actor が引き継がれる認識です。 Task.detached だと context を引き継がないので、 @MainActor な API から呼び出しても MainActor の世界にならないです。
Avatar
Avatar
niw
YouTube みたいにタイムスタンプでリンクできたらいいのにな (edited)
秒でカウントしたタイムスタンプ付きでリンクできそう https://developer.apple.com/videos/play/wwdc2021/10134/?time=1585
When you have code that needs to run at the same time as other code, it's important to choose the right tool for the job. We'll take you...
👀 1
Avatar
おー
Avatar
外側というのは、スコープの外側って感じなんですかね。実行時のスタックとは無関係で。
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0304-structured-concurrency.md at main · apple/swift-evolution
Avatar
Avatar
hironytic
秒でカウントしたタイムスタンプ付きでリンクできそう https://developer.apple.com/videos/play/wwdc2021/10134/?time=1585
そうでした。たしか Transcript をクリックすると、その time 付きリンクに飛ぶんですよね。
Avatar
@_inheritActorContext がActor引き継ぎマークっぽいですね。 Task.initにだけ付いてる 👀 https://github.com/apple/swift/blob/main/docs/ReferenceGuides/UnderscoredAttributes.md#_inheritactorcontext
👀 2
Avatar
actorのメソッドの中で作られたTaskには引き継がれる認識があったけど、actorのメソッド内で作ったクロージャーの中で作ったTaskに引き継がれるとは思ってなかったんですよね。思い込みで。
Avatar
Avatar
Yuta Saito
@_inheritActorContext がActor引き継ぎマークっぽいですね。 Task.initにだけ付いてる 👀 https://github.com/apple/swift/blob/main/docs/ReferenceGuides/UnderscoredAttributes.md#_inheritactorcontext
@_implicitSelfCapture に続いてw
Avatar
Avatar
hironytic
秒でカウントしたタイムスタンプ付きでリンクできそう https://developer.apple.com/videos/play/wwdc2021/10134/?time=1585
知見...!
Avatar
Avatar
hironytic
actorのメソッドの中で作られたTaskには引き継がれる認識があったけど、actorのメソッド内で作ったクロージャーの中で作ったTaskに引き継がれるとは思ってなかったんですよね。思い込みで。
この前自分の発表聞きながらよくわからなくなったのは、↓の sink の中が MainActor 上と判定されるのはなんでだろう?ということですね。もしかしたら、ひろんさんもこのことを言ってる?( Task が出てきてないから違う?) state .objectWillChange .receive(on: DispatchQueue.main) .sink { [self] _ in // state を View に反映する処理 nameLabel.text = state.user?.name } .store(in: &cancellables) どこかで、 Task.init はできるだけコンテクストを推定するみたいなのを読んだ気がしていて、 DispatchQueue.main から推定されている?
Avatar
そうそうそれを言ってます。
2:08 AM
あ違う。sink の中がじゃないや、 sink の中で Task を作った中が、というのがぼくの言ってるやつ。
2:11 AM
うん?やっぱり同じことを言ってる? つまり、 sink の中は( receive(on:) してなかったら)メインスレッドで動く保証はないと思ってた(実際どうなんだろう 🤔 )んだけど、そこから作った Task には @MainActor が効いてくるのかと思って。
2:13 AM
ちなみに、ViewControllerの外側にグローバル関数作っておいて、その中から Task を作るようにして、この sink の中でそのグローバル関数を呼んでも、その Task 内(の、await後)はメインスレッドで動いていなかった。そりゃそうだろなとは思いましたが。
2:18 AM
だからやっぱり、スコープの外側っていう言い方が合ってるかどうかわからないけど、例えば private 変数にアクセスできるかどうかと同じような感じで、実行時のコンテキストには関係なくて、コードの外側にある actor が引き継がれるのかなという結論に落ち着きつつあります。
Avatar
Marks that a @Sendable async closure argument should inherit the actor context based on the declaration site of the closure.
なのでひろんさんの認識であってると思います
Avatar
Avatar
koher
この前自分の発表聞きながらよくわからなくなったのは、↓の sink の中が MainActor 上と判定されるのはなんでだろう?ということですね。もしかしたら、ひろんさんもこのことを言ってる?( Task が出てきてないから違う?) state .objectWillChange .receive(on: DispatchQueue.main) .sink { [self] _ in // state を View に反映する処理 nameLabel.text = state.user?.name } .store(in: &cancellables) どこかで、 Task.init はできるだけコンテクストを推定するみたいなのを読んだ気がしていて、 DispatchQueue.main から推定されている?
ちなみに sink の中って MainActor 上で実行されるんでしょうか?だとしたら、 reveive(on: DispatchQueue.main) を消しても大丈夫?
2:34 AM
いや、 receive(on:) を消したら、sink の中はメインスレッドとは限らなかった (edited)
Avatar
Avatar
hironytic
ちなみに sink の中って MainActor 上で実行されるんでしょうか?だとしたら、 reveive(on: DispatchQueue.main) を消しても大丈夫?
まず、 receive(on: DispatchQueue.main) した上でだと sink の中はメインスレッド上で実行されるので(そして MainActorDispatchQueue.main を使うので、事実上 MainActor に守られているのと同じだと思います。で、わかっていることは、その sink の中に書いたコードは MainActor 上と判定されるようです( MainActor に isolate された API を同期的に呼び出せるので)。
Avatar
そうですね。
2:39 AM
面白いのは、 receive(on: DispatchQueue.main) を外したら、 sink の中はメインスレッドとは限らないけど、その sink の中で Task を作ったら、そこに渡したクロージャの中はメインスレッドになる。
2:41 AM
DispatchQueue.main が事実上 MainActor と同じだというのは当然だけど、なんでコンパイラはそれがわかるんだろう
Avatar
あー、sinkのActorではなくその更に外のVCのActorを継承してるんですかね
Avatar
で、 Case 20 であればそもそも state@MainActor なので receive(on: DispatchQueue.main) しなくても sink はメインスレッド上なんですが、 receive(on: DispatchQueue.main) しているのは別の事情で、 objectWillChange なのでそのまま購読すると will なのでまだ変更が反映されてないんです。
2:42 AM
did change な状態にするために 1 サイクル遅らせたくて入れている。
Avatar
Avatar
Yuta Saito
あー、sinkのActorではなくその更に外のVCのActorを継承してるんですかね
これがよくわかんなくて、その外の VC の Actor を継承とかできるんですっけ?たとえば、 receive(on: DispatchQueue.global()) する場合とか考えると変なような。
Avatar
Avatar
Yuta Saito
あー、sinkのActorではなくその更に外のVCのActorを継承してるんですかね
そうそう、だから sink (をコールする側の) actor が引き継がれるんじゃなくて、ソース上で Task 生成を囲んでいる actor が引き継がれるのかなと。
Avatar
receive(on: DispatchQueue.global()) を挟んだ場合でも、 sink に渡すクロージャが再度 MainActor に投入される?
Avatar
Avatar
koher
receive(on: DispatchQueue.global()) を挟んだ場合でも、 sink に渡すクロージャが再度 MainActor に投入される?
Yes!
Avatar
試してみると、コンパイルは通るけど実行時に↓でした。 UILabel.text must be used from main thread only
Avatar
ん?違う
Avatar
ですね。
2:47 AM
コンパイラは MainActor に投入されると判断してるけど、実際の挙動はそうなってない?
Avatar
↓これで、ViewController 1 は別スレッドで、2と3はメインスレッドで呼ばれます。 state .objectWillChange .receive(on: DispatchQueue.global()) .sink { [weak self] _ in guard let self = self else { return } printIsMainThread("ViewController 1") Task { printIsMainThread("ViewController 2") _ = await self.state.user printIsMainThread("ViewController 3") } } .store(in: &cancellables)
Avatar
ええ…
2:48 AM
なんでだろ。Taskの中で同期で呼べば、静的に決まってるActorにホップした状態で実行されるはずなのに。
Avatar
Avatar
hironytic
↓これで、ViewController 1 は別スレッドで、2と3はメインスレッドで呼ばれます。 state .objectWillChange .receive(on: DispatchQueue.global()) .sink { [weak self] _ in guard let self = self else { return } printIsMainThread("ViewController 1") Task { printIsMainThread("ViewController 2") _ = await self.state.user printIsMainThread("ViewController 3") } } .store(in: &cancellables)
なるほど・・・。その 2, 3 はメインスレッドになるのか。
Avatar
Avatar
koher
試してみると、コンパイルは通るけど実行時に↓でした。 UILabel.text must be used from main thread only
これはTask.initのクロージャの中でUILabel操作したときですか?
Avatar
僕が試したのは↓ですね。 state .objectWillChange .receive(on: DispatchQueue.global()) .sink { [self] _ in nameLabel.text = state.user?.name // UILabel.text must be used from main thread only } .store(in: &cancellables)
Avatar
ああ、それはダメですね
Avatar
これはコンパイル時に検出はできない??
2:50 AM
これまでも書けたコードだから無理か。 (edited)
Avatar
UILabelにアクターの保護が付いていれば検出できるのかなぁ
Avatar
この場合に、ひろんさんが試した場合に sink の中に Task を書いたら MainActor 上になるというのがよくわからなくて、 sink に渡すクロージャをクロージャ式じゃなくて別の場所に宣言したグローバル関数だとどうなるんでしょう?
2:52 AM
ちなみに、ViewControllerの外側にグローバル関数作っておいて、その中から Task を作るようにして、この sink の中でそのグローバル関数を呼んでも、その Task 内(の、await後)はメインスレッドで動いていなかった。そりゃそうだろなとは思いましたが。 だ
これか。
Avatar
func outerFunc(state: UserViewState) { printIsMainThread("outerFunc 1") Task { printIsMainThread("outerFunc 2") _ = await state.user printIsMainThread("outerFunc 3") } } class ViewController: UIViewController { ... state .objectWillChange .receive(on: DispatchQueue.global()) .sink { [weak self] _ in guard let self = self else { return } outerFunc(state: self.state) printIsMainThread("ViewController 1") Task { printIsMainThread("ViewController 2") _ = await self.state.user printIsMainThread("ViewController 3") } } .store(in: &cancellables) ... }
2:52 AM
これだと、outerFunc 1〜3は全部別スレッドから
Avatar
なるほど。 .receive(on: DispatchQueue.main) だと outerFunc でもメインスレッド?
2:54 AM
あれ?今気づいたけどこれ僕のコード sink[self] になってるのミスってますね。
Avatar
mainだと、outerFunc 1はメインスレッド。outerFunc 2と3は別スレッドです。
Avatar
非同期単発で [self] 書きまくってたのにつられてて [weak self] じゃないといけないところまで [self] になってる。
Avatar
あえて目立つようにキャプチャーしてるのかと思ってたw > [self]
Avatar
Avatar
hironytic
mainだと、outerFunc 1はメインスレッド。outerFunc 2と3は別スレッドです。
えー、そうなんですね。じゃあメインスレッド上で実行されていることから推定して context を引き継ぐんじゃなくて、 @MainActor な API の中に書かれたクロージャ式であることが重要なのか。
Avatar
だと思います。実行時のコンテキストを引き継ぐんではなくて、Task を作るコードを書いたところがどのアクターの中にあるかなんだと思います。
Avatar
それちょっと気持ち悪いですね・・・。
Avatar
それが、private なメンバにアクセスできるかどうか、というのに似てるなと。
Avatar
クロージャ式で書いていたコードを切り出して関数にしたら挙動が変わるということですよね・・・。
Avatar
そうです。リファクタリングするとき危険です。
Avatar
それが、private なメンバにアクセスできるかどうか、というのに似てるなと。
outerFunc でなく同じインスタンスのメソッドだと?
3:00 AM
そもそも MainActor か。
Avatar
同じインスタンスのメソッドなら大丈夫じゃないかな。
3:00 AM
はい、そもそも MainActor だから。
Avatar
Task に渡すクロージャは基本的にメンバーにアクセスしたいはずで、そう考えると問題ないのかなぁ。 (edited)
3:01 AM
そんなことないか?
3:02 AM
Task から思い非同期タスクを発火して結果を返したいこととかもあるか。
3:02 AM
いや、でもクロージャの中でメンバにアクセスして結果を戻さないなら、どこで実行されようが同じだし、メンバにアクセスするならクロージャ式か同じインスタンスのメソッドになるか。
Avatar
sink の中で作ったTask の中で ViewController の private メンバにはアクセスできるけど、outerFunc の中では private メンバには当然アクセスできない。これと同じことだとは思うので、まあ、自分的には納得しました。
3:04 AM
今回みたいに、outerFunc にメンバを引数で渡すようするようなリファクタリングをしてしまうと、事故りますねw (edited)
Avatar
outerFunc、@MainActor がついてないからそれだけでかなり怖い存在になってるの感
Avatar
Avatar
hironytic
今回みたいに、outerFunc にメンバを引数で渡すようするようなリファクタリングをしてしまうと、事故りますねw (edited)
self.state は actor isolated だからそれ自体は問題ない?
Avatar
actor A と actor B で全く同じ処理してるやんー、ってことで、そこを共通メソッドに切り出して、ああ、メンバがとれないから引数で渡すようにして・・・ってやれば事故を起こせそう
Avatar
Avatar
hironytic
actor A と actor B で全く同じ処理してるやんー、ってことで、そこを共通メソッドに切り出して、ああ、メンバがとれないから引数で渡すようにして・・・ってやれば事故を起こせそう
事故を起こせそうだけど、切り出した処理の中から Task のイニシャライザを呼びたいケースが限定的な気はします。
3:12 AM
というか、そもそも Task にそのメンバを渡せない? @Sendable でひっかかる?
3:13 AM
逆にメンバが Sendable なら事故らない?
Avatar
Avatar
koher
というか、そもそも Task にそのメンバを渡せない? @Sendable でひっかかる?
これはどういう意味です? 今回のぼくの例のように outerFunc の中の Task に state を渡すことはできます。
3:14 AM
state自体はstateのアクターで保護されてるけど、Task の中の処理が actor A と actor B で保護されないという感じか。
Avatar
Avatar
hironytic
これはどういう意味です? 今回のぼくの例のように outerFunc の中の Task に state を渡すことはできます。
stateactor だから state 自体は破壊できないし、前後の処理が VC のメンバにアクセスするならそれも isolated じゃないといけないし、そうでなければどこで実行されても大差ない?
Avatar
呼び出し先がactorになっていれば、「あれ?なんでここでawait呼ばないといけないんだ?」ってなる 一方、まだactorになっていないものをメインスレッドだと思い込んで呼ぶと事故が起きる、ということかな?と思いました。
Avatar
Task.init に渡すクロージャは @Sendable なので壊せるようなものを渡そうとすること自体ができない?
3:21 AM
なんかよくわからなくなってきた。 UIView って @MainActor なのになんでさっきの nameLable.text = UILabel.text must be used from main thread only になったんだっけ?? https://developer.apple.com/documentation/uikit/uiview
3:22 AM
ちょっと用事で離脱します・・・。 (edited)
Avatar
クロージャーの中身は、そのクロージャーを呼び出したスレッドから同期的に実行されるから・・・ですかね。 (edited)
3:23 AM
sink に渡すクロージャーは sendable でもなんでもないので。 (edited)
3:27 AM
まあ、そもそも Task 関係なく、 別の actor の中の処理を、共通だからって切り出そうと考えることが愚かな行為か・・・ 😓
3:31 AM
ただ、基底クラスの UIViewController@MainActor だから、自分では意識せず @MainActor になっていて、アクターが違うとか考えずに切り出すと、今まで意識することなくメインスレッドで動いていた Task の中身が、切り出したら別スレッドで実行されることがあるようになるということか。(ぼくも離脱します)
Avatar
Avatar
koher
なんかよくわからなくなってきた。 UIView って @MainActor なのになんでさっきの nameLable.text = UILabel.text must be used from main thread only になったんだっけ?? https://developer.apple.com/documentation/uikit/uiview
僕もこれずっと気になってます🤔 ↓も似た質問なのかなと思っていて、このやり取りで直ったと言っているのですが、RC以降でも引っかかりますね(僕の勘違いで全然関係ない話かもしれないですが...) そもそもawait付けないでアクセスできるのがおかしいのか...?DispatchQueueと混ざっているのが問題なのか...?構文上はMainActorに見えるので、receiveでThreadが切り替わっていることがわからない…?すいません書いてたらよくわからなくなってきました😅 https://forums.swift.org/t/await-in-async-function-isolated-to-mainactor-resumes-on-non-main-thread-bug/51957/2 https://github.com/apple/swift/pull/38768 (edited)
Avatar
このコミットで@escapingクロージャに対するactor-isolationの制約が無効になって、escapingクロージャが定義位置のアクターを引き継ぐようになったようです。 non-escapingであれば、関数の脱出までに寿命が尽きるので、スレッドを跨ぐことはないので、アクターを引き継ぐ仮定は正しいです。 escapingではこの仮定は明らかに安全ではないんですが、既存のコードを壊さないための妥協として5.5に入ってるそうです。 https://github.com/apple/swift/commit/5ecb9ebec2168582e0197453ba06b7d556e680fd で、Combineのsinkは、渡したクロージャの実行スレッドがreceiveで変わってしまうので、まさにその安全でないケースだった、ということだと思います。 (edited)
👀 3
Avatar
Avatar
koher
なんかよくわからなくなってきた。 UIView って @MainActor なのになんでさっきの nameLable.text = UILabel.text must be used from main thread only になったんだっけ?? https://developer.apple.com/documentation/uikit/uiview
なので、現状のコンパイラのactor-isolated判定がゆるく、sinkに渡したクロージャが呼び出し元のMainActor-isolatedを引き継いだため、MainActorでisolatedされているUILabelへの代入がawait無しでできた。しかし実際はスレッドが変わっているのでisolatedではなく、実行時に怒られる。 ということではないですかね。 (edited)
👀 2
Avatar
既存のコードを壊さないための妥協
警告が出るようになってくれたら安心だね。できるだろうか
(edited)
Avatar
Swift 6では壊れるんですが、そのための準備として警告を出すモードがあって、
8:35 AM
-warn-concurrency フラグを付けるとSwift 6で違法になるコードにワーニングを出してくれるんですが、なんかこのケースは動いてないっぽい…
😭 1
Avatar
ありがとうございます!なるほど現状チェックされないケースがあるんですね。
-warn-concurrency フラグを付けるとSwift 6で違法になるコードにワーニングを出してくれるんですが、なんかこのケースは動いてないっぽい…

僕もさっきmainリポジトリのsnapshotで同じこと試したのですが、警告も何も出てこなかったですね...
(edited)
😂 1
Avatar
なんか忘れられてそうなのでチケット作りました。https://bugs.swift.org/browse/SR-15235
🙏🏻 5
Avatar
Avatar
Yuta Saito
なので、現状のコンパイラのactor-isolated判定がゆるく、sinkに渡したクロージャが呼び出し元のMainActor-isolatedを引き継いだため、MainActorでisolatedされているUILabelへの代入がawait無しでできた。しかし実際はスレッドが変わっているのでisolatedではなく、実行時に怒られる。 ということではないですかね。 (edited)
よく考えたらsetterだからasyncにできないし、nonisolatedなんでしょうか?setterだけnonisolatedとかできるのかわからないですが。元がObj-Cだし、余計複雑?nonisolatedじゃなくて、MainActorの外からsetterが見えないのが正解?
Avatar
setterの場合は foo.bar = await .... になるのでは?と思ったが果たして
Avatar
プロパティのエフェクトはgetだけ
Avatar
そうか、セッタか
Avatar
理論上setter側で止めたいとしても、それは値を渡す側で待ち受けるんじゃないかってことですね
10:57 AM
今の状態だとsetterに副作用とか紛れ込ませて違法コンカレンシーやりたい放題だな…
Avatar
更新処理を関数に出してもawaitなしで関数呼び出しできますね(チェックしてないのでそうなんですが...) nameLabel にアクセスしているところでこういう感じのエラー(警告)が出て欲しいです (edited)
Avatar
Avatar
shiz
更新処理を関数に出してもawaitなしで関数呼び出しできますね(チェックしてないのでそうなんですが...) nameLabel にアクセスしているところでこういう感じのエラー(警告)が出て欲しいです (edited)
出てほしいですよね。ただ、エラーにしてしまうと既存コードが軒並み通らなくなるから厳しい?警告が限界でしょうか。
1:36 PM
Concurrency 的に正しいコードは↓のようになるんでしょうか。 state .objectWillChange .sink { [weak self] _ in guard let self = self else { return } Task { await MainActor.run { // state を View に反映する処理 self.nameLabel.text = self.state.user?.name } } } .store(in: &cancellables)
1:39 PM
TaskMainActor.run を統合したい( Task にイニシャライザに Actor の context を明示的に渡したい)なぁ。
1:42 PM
本当にほしいのは、 ObservableObjectactor の場合は、その actor に isolate された状態で購読する手段か。
Avatar
Avatar
koher
出てほしいですよね。ただ、エラーにしてしまうと既存コードが軒並み通らなくなるから厳しい?警告が限界でしょうか。
> 出てほしいですよね。ただ、エラーにしてしまうと既存コードが軒並み通らなくなるから厳しい?警告が限界でしょうか。
今のSwift Coreチーム(Dougさん?)の考えだと、Swift5.X + -warn-concurrencyフラグで警告、Swift6にしたらエラーという流れになる感じなのかなと僕は思ってます。
Concurrency 的に正しいコードは↓のようになるんでしょうか。
どんな状況でもMainActorで呼び出したい場合はそうなるのかなと思ってます。ただ今回のケースだとUILabelを扱うのがUIViewControllerの中以外だとないのかなと思っており、MainActor.runは必要ないのではと思いました(どうなんでしょう?)🤔
Avatar
Avatar
shiz
> 出てほしいですよね。ただ、エラーにしてしまうと既存コードが軒並み通らなくなるから厳しい?警告が限界でしょうか。
今のSwift Coreチーム(Dougさん?)の考えだと、Swift5.X + -warn-concurrencyフラグで警告、Swift6にしたらエラーという流れになる感じなのかなと僕は思ってます。
Concurrency 的に正しいコードは↓のようになるんでしょうか。
どんな状況でもMainActorで呼び出したい場合はそうなるのかなと思ってます。ただ今回のケースだとUILabelを扱うのがUIViewControllerの中以外だとないのかなと思っており、MainActor.runは必要ないのではと思いました(どうなんでしょう?)🤔
Swift5.X + -warn-concurrencyフラグで警告、Swift6にしたらエラーという流れ
なるほど。
ただ今回のケースだとUILabelを扱うのがUIViewControllerの中以外だとないのかなと
あー、 TaskMainActor を受け継ぐからということですね。↑でひろんさんと話していた、 actor-isolated な API の中に書かれたクロージャ式の中に書かれた Task は元の actor-isolated な context を引き継ぐというので満たされているということですね。
(edited)
Avatar
Avatar
koher
Swift5.X + -warn-concurrencyフラグで警告、Swift6にしたらエラーという流れ
なるほど。
ただ今回のケースだとUILabelを扱うのがUIViewControllerの中以外だとないのかなと
あー、 TaskMainActor を受け継ぐからということですね。↑でひろんさんと話していた、 actor-isolated な API の中に書かれたクロージャ式の中に書かれた Task は元の actor-isolated な context を引き継ぐというので満たされているということですね。
(edited)
あー、 Task が MainActor を受け継ぐからということですね。↑でひろんさんと話していた、 actor-isolated な API の中に書かれたクロージャ式の中に書かれた Task h元の actor-isolated な context を引き継ぐというので満たされているということですね。
はい、そうですね!
Avatar
actor-isolated な context を引き継ぐ条件がよくわからなくなってきました・・・。 @MainActor な API で↓を実行したときに、 print("#0", Thread.current, Thread.current == Thread.main) Task { print("#1a", Thread.current, Thread.current == Thread.main) Task { print("#1b", Thread.current, Thread.current == Thread.main) } } task { print("#2a", Thread.current, Thread.current == Thread.main) Task { print("#2b", Thread.current, Thread.current == Thread.main) } } Task.detached { print("#3a", Thread.current, Thread.current == Thread.main) Task { print("#3b", Thread.current, Thread.current == Thread.main) } } taskDetached { print("#4a", Thread.current, Thread.current == Thread.main) Task { print("#4b", Thread.current, Thread.current == Thread.main) } } DispatchQueue.main.async { print("#5a", Thread.current, Thread.current == Thread.main) Task { print("#5b", Thread.current, Thread.current == Thread.main) } } dispatchQueueMainAsync { print("#6a", Thread.current, Thread.current == Thread.main) Task { print("#6b", Thread.current, Thread.current == Thread.main) } } DispatchQueue.global().async { print("#7a", Thread.current, Thread.current == Thread.main) Task { print("#7b", Thread.current, Thread.current == Thread.main) } } dispatchQueueGlobalAsync { print("#8a", Thread.current, Thread.current == Thread.main) Task { print("#8b", Thread.current, Thread.current == Thread.main) } }
2:23 PM
(なお、 task などはそれとペアにある Task { } などをただラップしただけの関数です。)
2:23 PM
結果は↓のようになりました。 #0 <_NSMainThread: 0x6000035f4000>{number = 1, name = main} true #1a <_NSMainThread: 0x6000035f4000>{number = 1, name = main} true #1b <_NSMainThread: 0x6000035f4000>{number = 1, name = main} true #2a <NSThread: 0x6000035eac00>{number = 6, name = (null)} false #2b <NSThread: 0x6000035eac00>{number = 6, name = (null)} false #3a <NSThread: 0x6000035f6500>{number = 4, name = (null)} false #3b <NSThread: 0x6000035f6500>{number = 4, name = (null)} false #4a <NSThread: 0x6000035fc4c0>{number = 5, name = (null)} false #4b <NSThread: 0x6000035fc4c0>{number = 5, name = (null)} false #5a <_NSMainThread: 0x6000035f4000>{number = 1, name = main} true #5b <_NSMainThread: 0x6000035f4000>{number = 1, name = main} true #6a <_NSMainThread: 0x6000035f4000>{number = 1, name = main} true #6b <_NSMainThread: 0x6000035f4000>{number = 1, name = main} true #7a <NSThread: 0x600003571780>{number = 8, name = (null)} false #7b <_NSMainThread: 0x6000035f4000>{number = 1, name = main} true #8a <NSThread: 0x6000035b2440>{number = 3, name = (null)} false #8b <_NSMainThread: 0x6000035f4000>{number = 1, name = main} true
2:24 PM
1b, 5b, 6b, 7b, 8b のみ context が引き継がれている。
2:25 PM
1b が OK なのに 2b は context が引き継がれず、にも関わらず 8b は引き継がれているのとか謎じゃないでしょうか。
👀 1
Avatar
外側のタスクに影響されてるってことかな
Avatar
外側のタスクに影響されてるってことかな
みたいですね。呼び出し側のスレッドに依っているような気がします。(コードの生成のされ方で変わる...?) @MainActorを付けいない関数に抽出して実行するとまた違う結果が出て来ました。 #0 <_NSMainThread: 0x6000022e43c0>{number = 1, name = main} true #1a <NSThread: 0x6000022bc840>{number = 5, name = (null)} false #1b <NSThread: 0x6000022bc840>{number = 5, name = (null)} false #2a <NSThread: 0x6000022f0040>{number = 6, name = (null)} false #2b <NSThread: 0x6000022f0040>{number = 6, name = (null)} false #3a <NSThread: 0x6000022e8f00>{number = 8, name = (null)} false #3b <NSThread: 0x60000226d140>{number = 9, name = (null)} false #4a <NSThread: 0x6000022dedc0>{number = 7, name = (null)} false #4b <NSThread: 0x6000022dedc0>{number = 7, name = (null)} false #5a <_NSMainThread: 0x6000022e43c0>{number = 1, name = main} true #5b <_NSMainThread: 0x6000022e43c0>{number = 1, name = main} true #6a <_NSMainThread: 0x6000022e43c0>{number = 1, name = main} true #6b <NSThread: 0x6000022bc840>{number = 5, name = (null)} false #7a <NSThread: 0x60000226d140>{number = 9, name = (null)} false #7b <NSThread: 0x60000226d140>{number = 9, name = (null)} false #8a <NSThread: 0x6000022bc840>{number = 5, name = (null)} false #8b <NSThread: 0x6000022bc840>{number = 5, name = (null)} false
(edited)
Avatar
@MainActor付き関数 #0 <_NSMainThread: 0x600003dbc700>{number = 1, name = main} true #1a <_NSMainThread: 0x600003dbc700>{number = 1, name = main} true #1b <_NSMainThread: 0x600003dbc700>{number = 1, name = main} true #2a <NSThread: 0x600003d84140>{number = 7, name = (null)} false #2b <_NSMainThread: 0x600003dbc700>{number = 1, name = main} true #3a <NSThread: 0x600003dfcc80>{number = 3, name = (null)} false #3b <NSThread: 0x600003dfcc80>{number = 3, name = (null)} false #4a <NSThread: 0x600003d80340>{number = 8, name = (null)} false #4b <_NSMainThread: 0x600003dbc700>{number = 1, name = main} true #5a <_NSMainThread: 0x600003dbc700>{number = 1, name = main} true #5b <_NSMainThread: 0x600003dbc700>{number = 1, name = main} true #6a <_NSMainThread: 0x600003dbc700>{number = 1, name = main} true #6b <_NSMainThread: 0x600003dbc700>{number = 1, name = main} true #7a <NSThread: 0x600003d84140>{number = 7, name = (null)} false #7b <NSThread: 0x600003d84140>{number = 7, name = (null)} false #8a <NSThread: 0x600003df7580>{number = 4, name = (null)} false #8b <_NSMainThread: 0x600003dbc700>{number = 1, name = main} true (edited)
Avatar
うおー、なんかわからんくなってきた。 あーでも、falseなら「MainActorが引き継がれてない」のはいえますが、trueの場合は「MainActorが引き継がれているかどうかは不明」ですね。
Avatar
MainActorは内部的にMainActorとDispatchQueue.mainは同期していて、MainThreadで実行されることは保証されているけど、MainThreadで実行されていてもMainActorであるという訳ではない、ということですかね?WWDCでMainThreadは協調スレッドプールとは切り離されていると言っていたので、MainThreadはMainActorでしか使えず、他のExecutorがMainThreadを使うことはないのかなと思ってました🤔 あ、でもCustom Executor使えばできるのかな…🤔 (edited)
Avatar
引き継がれる条件がぜんぜんわからないですね・・・
Avatar
@discardableResult func task<Success>(operation: @escaping @Sendable () async -> Success) -> Task<Success, Never> { return Task.init(operation: operation) } @discardableResult func taskDetached<Success>(operation: @escaping @Sendable () async -> Success) -> Task<Success, Never> { return Task.detached(operation: operation) } func dispatchQueueMainAsync(execute work: @escaping () -> Void) { DispatchQueue.main.async(execute: work) } func dispatchQueueGlobalAsync(execute work: @escaping () -> Void) { DispatchQueue.global().async(execute: work) } func dispatchQueueMainAsyncSendable(execute work: @escaping @Sendable () -> Void) { DispatchQueue.main.async(execute: work) } func dispatchQueueGlobalAsyncSendable(execute work: @escaping @Sendable () -> Void) { DispatchQueue.global().async(execute: work) } と定義しておいて
11:22 PM
@MainActor をつけたクラスのメソッドから↓を実行 print("#0", Thread.current, Thread.current == Thread.main) Task { print("#1a", Thread.current, Thread.current == Thread.main) Task { print("#1b", Thread.current, Thread.current == Thread.main) } } task { print("#2a", Thread.current, Thread.current == Thread.main) Task { print("#2b", Thread.current, Thread.current == Thread.main) } } Task.detached { print("#3a", Thread.current, Thread.current == Thread.main) Task { print("#3b", Thread.current, Thread.current == Thread.main) } } taskDetached { print("#4a", Thread.current, Thread.current == Thread.main) Task { print("#4b", Thread.current, Thread.current == Thread.main) } } DispatchQueue.main.async { print("#5a", Thread.current, Thread.current == Thread.main) Task { print("#5b", Thread.current, Thread.current == Thread.main) } } dispatchQueueMainAsync { print("#6a", Thread.current, Thread.current == Thread.main) Task { print("#6b", Thread.current, Thread.current == Thread.main) } } DispatchQueue.global().async { print("#7a", Thread.current, Thread.current == Thread.main) Task { print("#7b", Thread.current, Thread.current == Thread.main) } } dispatchQueueGlobalAsync { print("#8a", Thread.current, Thread.current == Thread.main) Task { print("#8b", Thread.current, Thread.current == Thread.main) } } dispatchQueueMainAsyncSendable { print("#9a", Thread.current, Thread.current == Thread.main) Task { print("#9b", Thread.current, Thread.current == Thread.main) } } dispatchQueueGlobalAsyncSendable { print("#10a", Thread.current, Thread.current == Thread.main) Task { print("#10b", Thread.current, Thread.current == Thread.main) } }
11:23 PM
結果 #0 <_NSMainThread: 0x600002fb4140>{number = 1, name = main} true #1a <_NSMainThread: 0x600002fb4140>{number = 1, name = main} true #1b <_NSMainThread: 0x600002fb4140>{number = 1, name = main} true #2a <NSThread: 0x600002f82180>{number = 6, name = (null)} false #2b <NSThread: 0x600002f82180>{number = 6, name = (null)} false #3a <NSThread: 0x600002f82540>{number = 2, name = (null)} false #3b <NSThread: 0x600002f82540>{number = 2, name = (null)} false #4a <NSThread: 0x600002f82540>{number = 2, name = (null)} false #4b <NSThread: 0x600002f82540>{number = 2, name = (null)} false #5a <_NSMainThread: 0x600002fb4140>{number = 1, name = main} true #5b <_NSMainThread: 0x600002fb4140>{number = 1, name = main} true #6a <_NSMainThread: 0x600002fb4140>{number = 1, name = main} true #6b <_NSMainThread: 0x600002fb4140>{number = 1, name = main} true #7a <NSThread: 0x600002f82780>{number = 4, name = (null)} false #7b <_NSMainThread: 0x600002fb4140>{number = 1, name = main} true #8a <NSThread: 0x600002f82180>{number = 6, name = (null)} false #8b <_NSMainThread: 0x600002fb4140>{number = 1, name = main} true #9a <_NSMainThread: 0x600002fb4140>{number = 1, name = main} true #9b <NSThread: 0x600002f82540>{number = 2, name = (null)} false #10a <NSThread: 0x600002f82180>{number = 6, name = (null)} false #10b <NSThread: 0x600002f82180>{number = 6, name = (null)} false
11:24 PM
@Sendable のクロージャー内だと、クロージャーの外側のactor contextが引き継がれないってこと?
Avatar
Avatar
koher
1b, 5b, 6b, 7b, 8b のみ context が引き継がれている。
5b, 6b, 7b, 8b は全部 @Sendable じゃないクロージャー内で Task を作ってる。 一方、2b, 3b, 4b, (9b, 10b) は @Sendable なクロージャー内。 1b も @Sendable だけど、 Task.init には @_inheritActorContext がついてるとのことなのでこれは特別?
Avatar
通常のクロージャ式の中に Task.init が書かれた場合は actor の context を引き継ぐ、 @Sendable なクロージャ式の中に Task.init が書かれた場合は actor の context を引き継がない。ただし、 @_inheritActorContext が付与されている @Sendable なクロージャ式の中に書かれた Task.init は例外的に actor の context を引き継ぐ。ということですね。
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0306-actors.md at main · apple/swift-evolution
11:57 PM
Actors prevent this data race by specifying that a @Sendable closure (described in ...) is always non-isolated.
11:57 PM
@Sendable なクロージャの中はnon-isolatedなので引き継がないってことですね。
Avatar
おおお、この Closures のところ特に難しくて、前に読んだときふんわりとしか理解できなかったんですよね。今の問題意識で読めば理解できるのかも。
Avatar
今のぼくにはまだまだ部分的にしか理解できないw が、とりあえず引き継ぎの条件については「完全に理解した」のでとりあえず満足しておきます
Avatar
あー、これ文章が難しかったんですが、ここのコードの例は別に難しくなかったのを思い出してきました。 (edited)
Avatar
おお!完全に理解した
12:05 AM
(aka ちゃんと読む)
🤣 1
Avatar
↓が何を言ってるのか理解するのにめっちゃ苦労したけど、コードは大して難しくない。単に detach のクロージャ式の中が non-isolated だから await 必須だよと。
A task created with detach runs concurrently with all other code. If the closure passed to detach were to be actor-isolated, we would introduce a data race on access to the mutable state on BankAccount. Actors prevent this data race by specifying that a @Sendable closure ... is always non-isolated.
Avatar
@Sendable のクロージャー内だと、クロージャーの外側のactor contextが引き継がれない
12:08 AM
日本語だと、つまりこれが結論ってことでOKかな...
Avatar
ですね。
Avatar
で、その理由は、@Sendable なクロージャーは常に non-isolated だから。
Avatar
ですね!
Avatar
で、(多分)混乱の要因は Task.init のクロージャーは @_inheritActorContext だからと... (edited)
Avatar
今話題にしてるのって↓のパターンで、 bar が挟まってるからもう一段階複雑な気がしています。 @MainActor func foo() { // (A) MainActor bar { // (B) MainActor でない Task { // (C) ここは? } } } (edited)
12:12 AM
bar のクロージャが @Sendable でない場合に (C) が (A) の context を引き継ぐことはこの "Closures" からは読み取れないような? (edited)
👀 1
Avatar
実は問題は @_inheritActorContext の挙動ってことか...?
Avatar
いや、そもそも Task.init の引き継ぎの条件の話なので @_inheritActorContext の挙動そのものが話題というかw
Avatar
で、 bar のクロージャが @Sendable でない場合に (C) が (A) の context を引き継ぐのであれば、 bar のクロージャが @Sendable の場合に (C) が (A) の context を引き継ぐのかも自明でなくて( Task.init が呼び出された context が引き継がれるわけではないから)、調べてみたら引き継がれなかったと。 (edited)
Avatar
そうだった、なんか長くてわかんなくなってきたw
Avatar
(B) が MainActor ではないところが微妙
12:17 AM
でもそれは↓に関することだとしたら、現状はまだ正しい状態ではない? https://discord.com/channels/291054398077927425/291054454793306112/890513245801160744
Avatar
Task.init が呼び出された context が引き継がれるわけではないから
これが超絶わかりにくい気がします。これまで「呼び出された context 」が引き継がれるのだと思ってたし、それなら話はシンプルだけど。
Avatar
Avatar
hironytic
でもそれは↓に関することだとしたら、現状はまだ正しい状態ではない? https://discord.com/channels/291054398077927425/291054454793306112/890513245801160744
そうなんですよね。現状の挙動が正しいのかわからないのも余計にややこしい・・・。
Avatar
あと、メソッド名が確定するまでうろちょろしたので、過去のいろんな資料が見返すと混乱をまねく。。。
Avatar
今はなき detach ・・・。
12:22 AM
WWDC の資料も結構修正されてるんですけど(これはすごいと思った)、一部残っちゃってるんですよね。
Avatar
修正されてるんですか!それはすごい
Avatar
たとえば async { } の 7 割くらい(?)は Task { } に修正されてます。
👀 1
Avatar
まあ、そこ async って覚えてしまうと、いきなり躓きそう
Avatar
スライドレベルの修正で済むものは大体修正されているんですが、 https://developer.apple.com/videos/play/wwdc2021/10194/ みたいなスクリーンをレコーディングしたものは、おそらく修正が難しいことが原因で修正されていませんね。
Discover Swift concurrency in action: Follow along as we update an existing sample app. Get real-world experience with async/await,...
Avatar
ああ、それは収録しなおしになるから無理ですねw
Avatar
スライドが修正されたものについては、トークが修正されたかはわからないんですが、元々どっちになっても違和感がないように Transcript が考えられてたのかも。
Avatar
関係ないけど、これをみてVimモードはライブプレゼンには向かないと思いました。いきなり範囲選択無しに数行消えたりするので、何をやったのかわかりにくいw
😂 1
Avatar
たしかに・・・。
Avatar
Avatar
koher
Task.init が呼び出された context が引き継がれるわけではないから
これが超絶わかりにくい気がします。これまで「呼び出された context 」が引き継がれるのだと思ってたし、それなら話はシンプルだけど。
実行時のcontextが引き継がれるとしたら話はシンプルそうだけど、コンパイル時の静的型チェック(actor isolatedのチェック)は超絶難しそうですw
Avatar
Avatar
Yuta Saito
このコミットで@escapingクロージャに対するactor-isolationの制約が無効になって、escapingクロージャが定義位置のアクターを引き継ぐようになったようです。 non-escapingであれば、関数の脱出までに寿命が尽きるので、スレッドを跨ぐことはないので、アクターを引き継ぐ仮定は正しいです。 escapingではこの仮定は明らかに安全ではないんですが、既存のコードを壊さないための妥協として5.5に入ってるそうです。 https://github.com/apple/swift/commit/5ecb9ebec2168582e0197453ba06b7d556e680fd で、Combineのsinkは、渡したクロージャの実行スレッドがreceiveで変わってしまうので、まさにその安全でないケースだった、ということだと思います。 (edited)
escapingクロージャが定義位置のアクターを引き継ぐようになった
これはコンパイラが、アクターを引き継いでいると 判断するようになった という話で、エラーが出なくなるだけで実際にそのアクターに守られているわけではない、という理解で合ってますか?
Avatar
Avatar
hironytic
(B) が MainActor ではないところが微妙
↑の話で考えると、 (B) は最終的な仕様上 MainActor にならないし、現状でも MainActor に守られているわけではないけど、 self.nameLabel.text = ... みたいなのが書けないと既存コードが破壊されまくるので、現状ではコンパイラが MainActor 扱いにしてコードの互換性を保っている(ただし守られてはいない)、 Swift 6 では MainActor でなくなるし await 必須になる、ということになる? そして、それと bar をすっ飛ばして Task.initfoo の context を引き継ぐ話はまた別で、 @Sendable は actor の context をぶった切る、 @Sendable でない @escaping なクロージャが何かの actor の context を持つことはないと考えると、 Task.init に渡されるクロージャは、それが宣言された場所で最も近い(内側のスコープの) actor を引き継ぐと考えれば一般化できる? という感じでしょうか。
12:59 AM
// Actor 1 a { // @escaping // どの Actor でもない Task.init { // Actor 1 await MainActor.run { // MainActor b { // @escaping // どの Actor でもない Task.init { // MainActor c { // @Sendable @escaping // どの Actor でもない Task.init { // どの Actor でもない actor2 { // Actor 2 @Sendable @escaping // Actor 2 d { // @escaping // どの Actor でもない Task.init { // Actor 2 } } } } } } } } } }
1:00 AM
↑のような感じ?
Avatar
@Sendable でない @escaping なクロージャが何かの actor の context を持つことはない
あれ?これは引き継ぐのではないでしょうか?(わかんなくなってきましたw) Escaping closures can now be actor-isolated; only @Sendable prevents isolation. https://github.com/apple/swift-evolution/blob/main/proposals/0306-actors.md#revision-history @Sendable はnon-isolatedであるものの、 @_inheritActorContextが例外にしているのかと。 あーすいません上で既に話されてましたねw
(edited)
Avatar
僕が勘違いしてそうな気がしてきました・・・
Avatar
ぼくもsendableじゃないクロージャーなら引き継ぐのが正しいと思います。
Avatar
Remove the heuristic that escaping closures cannot be actor-isolated. This is in line with the long term plan for actor isolation, but opens up some holes in the short term because Sendable closures are not enforced throughout the Swift ecosystem.
https://github.com/apple/swift/commit/5ecb9ebec2168582e0197453ba06b7d556e680fd
1:05 AM
これは暫定的な対応ではなくて、恒久的対応だけど今はチェックが完全じゃないから穴が開いてるよってこと?
Avatar
ただ、正しく引き継ぐと、DispatchQueue.global().async { }の中もメインスレッドで実行されちゃって既存コードを破壊するということなんじゃないかなあ
Avatar
Avatar
koher
escapingクロージャが定義位置のアクターを引き継ぐようになった
これはコンパイラが、アクターを引き継いでいると 判断するようになった という話で、エラーが出なくなるだけで実際にそのアクターに守られているわけではない、という理解で合ってますか?
議論全部終えてないんですが、これはあってます
👀 1
Avatar
Avatar
koher
// Actor 1 a { // @escaping // どの Actor でもない Task.init { // Actor 1 await MainActor.run { // MainActor b { // @escaping // どの Actor でもない Task.init { // MainActor c { // @Sendable @escaping // どの Actor でもない Task.init { // どの Actor でもない actor2 { // Actor 2 @Sendable @escaping // Actor 2 d { // @escaping // どの Actor でもない Task.init { // Actor 2 } } } } } } } } } }
これコード読んで判断しろといわれても厳しいな (edited)
Avatar
現状だとただescapingなだけのクロージャはどのActorで実行されるか不定だけど、isolationが完了した理想世界ならActorを跨ぐescapingなクロージャは同時にSendableも付くはず (edited)
1:09 AM
過渡期において動作が不定のものが含まれてしまってるが、ということかな
Avatar
Avatar
hironytic
ただ、正しく引き継ぐと、DispatchQueue.global().async { }の中もメインスレッドで実行されちゃって既存コードを破壊するということなんじゃないかなあ
そっち側に壊れるのかぁ。
Avatar
たるのんさんの言うように、isolationが完了した理想世界はスレッド管理を言語外ではやらなくなるのでうまくいくのであって。
Avatar
「暫定的に Actor を引き継いでいると判定する(ただし守られてはいない)→最終的には引き継いでいないと判定するように変更」かと思っていたけど、「恒久的に Actor を引き継いでいると判定する(ただし現状では守られてはいない)→最終的には守られているようにする」ということ?
Avatar
sendableなクロージャーはnon-isolatedとして扱う、とわざわざ言うからには、sendableじゃないクロージャーならisolatedというのが自然ですよね
Avatar
そうすると、↓のように解釈すればいいってことでしょうか。 @MainActor func foo() { // (A) MainActor bar { // (B) MainActor (ただし現状は守られていない) Task { // (C) MainActor } } }
Avatar
isolationが完了した理想世界ならActorを跨ぐescapingなクロージャは同時にSendableも付くはず
こうなるとSendableチェックがきちんと働くので
「暫定的に Actor を引き継いでいると判定する(ただし守られてはいない)→最終的には引き継いでいないと判定するように変更」
僕はこっちなのかと思いました。
(edited)
Avatar
錯綜してきたw
Avatar
Avatar
koher
そうすると、↓のように解釈すればいいってことでしょうか。 @MainActor func foo() { // (A) MainActor bar { // (B) MainActor (ただし現状は守られていない) Task { // (C) MainActor } } }
barはbarを宣言したコンテキストのActorになります
1:14 AM
もしbarをSendable無しでActorを跨いで渡したのなら、それ自体が将来的に違反コード (edited)
Avatar
Avatar
tarunon
barはbarを宣言したコンテキストのActorになります
bar の宣言ではなく bar に渡すクロージャの宣言ですか?
Avatar
既存のDispatchQueueとかがアクターになってないのが根本の原因で、アクターになっているならsendableを受け取るように変わるからsendableじゃないクロージャーなんか受け取ることはないということかと
Avatar
あ、そうですね。クロージャがinitされたとき、です
Avatar
アクターを挟まずにスレッドを切り替える手段がないのが理想世界で、そうだとすると、barがsendableじゃないクロージャーを取るのなら、その先が別のスレッドではないわけで
Avatar
そうですそうです
Avatar
その世界で、 @Sendable でない @escaping ってどんなものが考えられますか?存在しない?
Avatar
逆にbarがスレッドを切り替えてクロージャーを実装するたぐいのものなら、sendableなクロージャーを取るようになむてるはずだと
Avatar
そのActorの中でしか使われないクロージャーとかじゃないですかね。結構色々ありそうだけど。 (edited)
1:19 AM
UIView.animateのcompletionとかが、当に
Avatar
今、メインスレッドしか使わずにプログラムしても生まれるescapingなクロージャーと同じですよね。後からいいタイミングで呼ぶ的なやつ
1:20 AM
メンバに持っといて、なんかの拍子で実行するとかそういう
Avatar
故に今出来ることは、スレッド跨ぎクロージャー渡しに全部@Sendableをつけて宣言するようニしておく、と言うことだと思います
👀 1
Avatar
(…離脱します)
Avatar
スレッド跨ぎクロージャーかつSendable無しは違法コード
1:21 AM
だから動作が不定になる
Avatar
既存のDispatchQueueとかがアクターになってないのが根本の原因
DispatchQueueactor なら async メソッドに渡すクロージャは @Sendable なはずで、そうすれば↓のようになるはずと。 @MainActor func foo() { // (A) MainActor DispatchQueue.global().async { // (B) global Task { // (C) global } } }
Avatar
そうですね、そうなると思います
1:33 AM
現状はDispatchQueue.global().asyncはActorの管轄外なのでそういう動きは出来ないんじゃないかな
Avatar
これを実行すると @MainActor func foo() { print("#0", Thread.current, Thread.current == Thread.main) DispatchQueue.global().async { print("#1", Thread.current, Thread.current == Thread.main) Task { print("#2", Thread.current, Thread.current == Thread.main) } } } final class ViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) foo() } } #0 <_NSMainThread: 0x60000250c000>{number = 1, name = main} true #1 <NSThread: 0x60000251c480>{number = 8, name = (null)} false #2 <NSThread: 0x60000251c480>{number = 8, name = (null)} false となるので、既にそうなっています?(あれ?) (edited)
Avatar
Avatar
tarunon
そうですね、そうなると思います
最終的に↓の (1), (2) と actor isolation はどのような関係になるという認識ですか? @MainActor func foo() { publisher .receive(on: DispatchQueue.global()) .sink { _ in // (1) Task { // (2) } } .store(in &cancellables) } (edited)
Avatar
sinkはSendableになるはずですね。故に1global, 2globalじゃないでしょうか。
1:40 AM
現状SwiftConcurrencyの外にあるところにいきなりTaskを生やすのが飛び道具過ぎる感覚はあります (edited)
1:40 AM
安全にやるならActorの宣言が先じゃないかな
Avatar
Avatar
shiz
これを実行すると @MainActor func foo() { print("#0", Thread.current, Thread.current == Thread.main) DispatchQueue.global().async { print("#1", Thread.current, Thread.current == Thread.main) Task { print("#2", Thread.current, Thread.current == Thread.main) } } } final class ViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) foo() } } #0 <_NSMainThread: 0x60000250c000>{number = 1, name = main} true #1 <NSThread: 0x60000251c480>{number = 8, name = (null)} false #2 <NSThread: 0x60000251c480>{number = 8, name = (null)} false となるので、既にそうなっています?(あれ?) (edited)
え、これって昨日の #7b と同じなのに挙動違いますよね??? Xcode 13.0 ?
Avatar
え、これって昨日の #7b と同じなのに挙動違いますよね??? Xcode 13.0 ?
はい、Xcode13.0です
Avatar
全てnullableだった世界にOptionalを入れたときと同じで、全部?(今回は明示的なActorの宣言)をつけないと正しくならない
1:43 AM
最悪実行する度に違うとしても、それはまあ現状脱法コードだしな、と言う感覚ですね (edited)
Avatar
viewDidAppear から直接だと Obj-C も絡んで挙動が違ってしまっているとか?? @shiz さんの foo の中身を viewDidAppearfoo の呼び出し箇所にコピペすると true, false, true ですか?
Avatar
あ、変わりましたw #0 <_NSMainThread: 0x6000023f8140>{number = 1, name = main} true #1 <NSThread: 0x6000023d82c0>{number = 8, name = (null)} false #2 <_NSMainThread: 0x6000023f8140>{number = 1, name = main} true (edited)
😂 1
😫 1
Avatar
こっちでも再現しました。
1:47 AM
何がなんだか・・・。
Avatar
@Sendable有りと無しの間に、未定義(つまりActorのContextを失う)を用意して、そのクロージャ下でのTaskの宣言をコンパイルエラーにする、と言うのが必要だったように見える
1:49 AM
DispatchQueue然り旧世界の非同期APIでActorにまだ対応してない箇所においては、そこに渡したクロージャの中からSwiftConcurrencyのAPIを呼ぶなら第一にActorの宣言が必要なはずです
Avatar
こういうことですね @MainActor func myFunc() { self.foo = .... // 合法 someActorsFunc { self.foo = ... // 違法 Task.init { // 合法 self.foo = ... // 違法 } } } @MainActor func myFunc() { self.foo = .... // 合法 DispatchQueue.global().async { self.foo = ... // 脱法 Task.init { // 脱法 self.foo = ... //脱法 } } } @MainActor func myFunc() { self.foo = .... // 合法 DispatchQueue.global().async { self.foo = ... // 脱法 Task.init { // 脱法 await MainActor.run { self.foo = .... // 合法 Task.init { // 合法 self.foo = ... //合法 } } } } } (edited)
👀 1
👍🏻 2
1:59 AM
メンバへのアクセス同様、Task.initの宣言にも脱法性がある
1:59 AM
1度脱法コンテキストに落ちたらその中のTaskの宣言も、その中のコンテキストも汚染されています (edited)
2:01 AM
本来なら脱法コンテキストのTask宣言は違法にして欲しかったけど、まあスケジュール的に仕様組むのも間に合わなかったんじゃないか
Avatar
Avatar
tarunon
こういうことですね @MainActor func myFunc() { self.foo = .... // 合法 someActorsFunc { self.foo = ... // 違法 Task.init { // 合法 self.foo = ... // 違法 } } } @MainActor func myFunc() { self.foo = .... // 合法 DispatchQueue.global().async { self.foo = ... // 脱法 Task.init { // 脱法 self.foo = ... //脱法 } } } @MainActor func myFunc() { self.foo = .... // 合法 DispatchQueue.global().async { self.foo = ... // 脱法 Task.init { // 脱法 await MainActor.run { self.foo = .... // 合法 Task.init { // 合法 self.foo = ... //合法 } } } } } (edited)
現状で↓のような挙動をしているのはどう解釈しますか?実装上たまたまそうなってるだけ? final class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // MainActor DispatchQueue.global().async { Task { // MainActor } } } }
2:16 AM
脱法で未定義?
Avatar
本来ならコンパイルエラーで然るべきだと思いますが、そうなってないので未定義の動作でたまたま望ましい方を引いているだけですかね。
Avatar
内側が意図せずに MainActor になるのって結構謎じゃないですか?さっきの shiz さんの foo の例があるから微妙ですが・・・。
Avatar
未定義なら何でもありじゃないかと
2:21 AM
コールスタックを遡るのかコンテキストを外側に辿るのかは知らないですけど、Actorコンテキストはそこにはないので、何かしらの方法で最寄りのActorコンテキストを拾ってきて埋めて動いてる。だから動きが不安定に見えているって事だと思います
Avatar
そうすると、一番最初の話に戻って、 iOS 15 で VC から Publisher を購読して View に反映する正しい書き方は↓? override func viewDidLoad() { super.viewDidLoad() state .objectWillChange .sink { [weak self] _ in guard let self = self else { return } Task { await MainActor.run { // state を View に反映する処理 self.nameLabel.text = self.state.user?.name } } } .store(in: &cancellables) }
Avatar
MainActor.runがTaskの外じゃないといけない
Avatar
それはできないです。
Avatar
あーそうなのか
Avatar
MainActor.runawait しないといけないので。
Avatar
そしたらそうですね、外側のTask.initを捨て石にしてMainActor.runを呼ばないといけない
Avatar
たとえ sink に渡すクロージャが @Sendable になったとして、 receive(on: DispatchQueue.main) したとしても、コンパイラはそれを検出できないから、 .sink { } の中が MainActor として判別することはできない・・・。
Avatar
どんな状況でもMainActorで呼び出したい場合はそうなるのかなと思ってます。ただ今回のケースだとUILabelを扱うのがUIViewControllerの中以外だとないのかなと思っており、MainActor.runは必要ないのではと思いました(どうなんでしょう?)🤔
なるほど。僕のこの認識が間違ってましたね。
Avatar
過渡期において汚染されたTaskが存在し得るというのがかなり重要ですね (edited)
Avatar
Avatar
shiz
どんな状況でもMainActorで呼び出したい場合はそうなるのかなと思ってます。ただ今回のケースだとUILabelを扱うのがUIViewControllerの中以外だとないのかなと思っており、MainActor.runは必要ないのではと思いました(どうなんでしょう?)🤔
なるほど。僕のこの認識が間違ってましたね。
うーん、僕はまだ仕様上なにが正しいのか自信を持ててません。 shiz さんがおっしゃってたのが正しい可能性もあるのかなと。
2:29 AM
なにせ現状で実際の挙動は当てにならないので😅
Avatar
なにせ現状で実際の挙動は当てにならないので
たしかにそうですねw結局何が本当に正しいのかがまだわからない😅
(edited)
😭 1
Avatar
Avatar
koher
たとえ sink に渡すクロージャが @Sendable になったとして、 receive(on: DispatchQueue.main) したとしても、コンパイラはそれを検出できないから、 .sink { } の中が MainActor として判別することはできない・・・。
これはちょっと違うと思っていて、DispatchQueue.mainではなく、MainActorのインスタンスを渡して型に焼き込む方法になるんじゃないかと。
Avatar
Avatar
tarunon
これはちょっと違うと思っていて、DispatchQueue.mainではなく、MainActorのインスタンスを渡して型に焼き込む方法になるんじゃないかと。
なるほど?でも任意の actor は型に現れないですよね?同じ型の異なるインスタンスは異なる actor だけど型が同じなので。
2:38 AM
Publisherの購読、AsyncSequenceを使うのが正解?でも無限ループだと循環参照がきついかぁ。
Avatar
Publisher自体がディスコンになるのは有り得ると思います
2:39 AM
JS世界もasync generatorがあるからRxわざわざ使うでもないって感じだし
2:40 AM
(最もあっちはReact/Vueの影響がかなり大きいけど)
2:41 AM
AsyncSequenceは、購読するときはちゃんとweakにしましょうねって話を前にやった気がする (edited)
Avatar
そうか、 Task.init があるからそこで weak capture すればいいのか。
3:35 AM
objectWillChange を購読するにしても for await 使うのが良さそうですねぇ。
Avatar
せっかく完全に理解したのに、shizさんの @MainActor のfooのやつで打ち砕かれたw やっぱり脱法はわけがわからない
😂 1
Avatar
脱法コードは書いちゃダメだよ(´・_・`)
Avatar
AsyncSequenceとして購読だと Sendable でない escaping クロージャがどこにも出てこないので明快ですね。
Avatar
tarunonさんが書いてるように、 @Sendable と、そうじゃないのと、それとは別に第3の「未定義」がマークできるのならまあわかるんだけど、その未定義というマークはないから、今はこれは「 @Sendable じゃない」になっているはずで、コンパイラからするとそこでスレッドの切り替えは発生しないとみるしかないはずだと思うんだけど。 (edited)
Avatar
未定義を作れなかった結果、旧世界のルールに落ちるのは別にこれに限った話じゃないと思います。
3:44 AM
JavaのOptional然り
Avatar
でも、 foo を経由しないとき(7b)はメインスレッドへの切り替えが発生してるし、fooを経由したら発生してないし。。。
Avatar
未定義動作であれば、そうなってもおかしくない (edited)
3:45 AM
宣言だけしたcのポインタに謎の数値が!?みたいな話です
Avatar
未定義は未定義なんだけど、コンパイラ上は未定義じゃないのに、7bでスレッドの切り替えは発生してるから、なんでかなーと。
3:47 AM
あー違うのか。MainActorだから、コンパイラからすると、新しくメインスレッドでタスクを実行してもいい(7b)し、そのまま継続してもいい(本来はスレッドの切り替えが発生しないのだからメインスレッドで実行されるはず)のか。
Avatar
コンテキストから外側のActorを拾ってるフロー(コンパイル時)と、コールスタックからActorのポインタを取ってくるフロー(実行時)の2通りがあるんじゃ無いだろうか
3:47 AM
基本コンパイル時解決するが、それが出来ない場合は実行時解決される。今は過渡期だから許してくれ、と。 (edited)
Avatar
そのまま継続しても、新しく乗せても、メインスレッドで実行されるはずなのに、脱法によって継続元が別のスレッドにいる場合ができてるから、コンパイラ的には意図せず、foo の方の末端の Task が false になってると考えれば辻褄はあう気がします。
3:49 AM
コンパイラがというよりは MainActor のglobalActorの実装が、ですかね。
3:51 AM
現在の DispatchQueue.async には @Sendable はついていないのだから、コンパイラのお気持ちとしては @MainActor func foo() { // ここはMainActor print("#0", Thread.current, Thread.current == Thread.main) DispatchQueue.global().async { // ここもMainActor print("#1", Thread.current, Thread.current == Thread.main) Task { // ここもMainActor print("#2", Thread.current, Thread.current == Thread.main) } } } (edited)
3:53 AM
だから、#1のprintが終わったあとのTaskをそのままそのスレッドで実行してもいいし、次のタイミングでメインスレッドで実行してもいい、と考えてよいはず。
Avatar
どちらでもいいですね
3:54 AM
なお #1 がウソなので…
Avatar
なのに脱法によって #1 のprintが実は別のスレッドで実行されているので、そのままのスレッドで実行する方に倒れたときに #2 もメインスレッドじゃなくなると。
Avatar
これまでの話を総合して得られた、 Swift Concurrency を考慮した正しい ObservableObject (の objectWillChange )の購読方法はこうかな。 override func viewDidLoad() { super.viewDidLoad() Task { [weak self] in guard let state = self?.state else { return } for await _ in state.objectWillChange.values { guard let self = self else { return } // state を View に反映する処理 self.nameLabel.text = self.state.user?.name } } }
Avatar
その Task 自体は ViewController が破棄されるときに cancel() してあげた方がいいのではなかろうか・・・
Avatar
明示的な Set<AnyCancellable>DisposeBag 相当のものは不要で、 VC が解放されたら guard let self = self else { return }Task.init を脱出する。
Avatar
あ、そうか。for await を抜けるから。 (edited)
Avatar
[weak self] と、 for await の中に guard let self = self else { return } があるのがポイントで、もし strong capture したり for await の前で guard let self = ... をやっちゃうとリークする。
Avatar
んー? 次の value が来るまでは脱出しない?
Avatar
Avatar
hironytic
んー? 次の value が来るまでは脱出しない?
ですね。ただ、それは明示的にキャンセルしても同じかと。
5:30 AM
TaskcancelisCancelled のフラグを立てるだけなので、 await したときにそこで使われている非同期 API が checkCancellation するか、自前で checkCancellation しない限りは終了しないので。
Avatar
AsyncSequence自体はキャンセルされないのかなあ
Avatar
Task が終了すると AsyncSequence をキャプチャするものがなくなるから、 AsyncSequence も解放されて、クリーンナップが必要ならそこで行われる?
Avatar
いや、Task をキャンセルしたら、AsyncSequence の next 待ちのところでキャンセルされないのかなあと思ったのです
Avatar
Task をキャンセルしたら next のところで CancellationErrorthrow されると思います。
5:33 AM
あー、でも for try await じゃないから無理?
Avatar
わからなくなってきた
Avatar
多分 for awaitnextnil を返してループ終了で Task が終了ですね。
Avatar
そうすると、次の値が来る前に終了しますよね、ということが言いたかった。
Avatar
あー、そういうことか。そうですね。
Avatar
omochimetaru 9/24/2021 5:37 AM
public protocol AsyncSequence { associatedtype AsyncIterator: AsyncIteratorProtocol where AsyncIterator.Element == Element associatedtype Element __consuming func makeAsyncIterator() -> AsyncIterator } public protocol AsyncIteratorProtocol { associatedtype Element mutating func next() async throws -> Element? }
Avatar
そして、ボタンを押すとかを起点にして値が更新される場合ヤバイな。
Avatar
omochimetaru 9/24/2021 5:37 AM
throws の無い AsyncSequence ってあるんですか?
Avatar
少なくとも for await の場合と for try await の場合がある。 (edited)
Avatar
omochimetaru 9/24/2021 5:38 AM
どういう規則でやってるんだろう
5:38 AM
AsyncSequence に conform している具体型の AsyncIterator.next() が nothrow なら
Avatar
Never のときに
Avatar
omochimetaru 9/24/2021 5:39 AM
コンパイラがそれを考慮する?
Avatar
NoThrowなasync sequence、たとえば NotificationCenterがそうかな
Avatar
あれ? AsyncSequenceFailure はない?
Avatar
omochimetaru 9/24/2021 5:40 AM
Publisher の エラー型がNeverならIteratorがnothrowってSwiftの文法で記述できないですよね (edited)
Avatar
(話が戻るけど)末端がこういう AsyncStream だと、ViewController がなくなったときにさっさとキャンセルしてくれたら onTermination がやってきてネットワークとの接続を切断できそう。 return AsyncStream(Item.self) { continuation in continuation.onTermination = { @Sendable _ in // ネットワークから切断 } // ネットワークに接続して // 値が来るたび continuation.yeild(item) するコードをここに }
Avatar
勝手に、 FailureNeverAsyncSequence では var next: Element { get async } がオーバーロードされてるのかと思ってた。
Avatar
omochimetaru 9/24/2021 5:41 AM
AsyncSequenceの定義にエラー型を表すassociatedtypeは無いように見えるんですよね。
Avatar
なんかその仕組み、 1 月の waiwai でややこしい話になって、そんなことほんとにできんの?ってなった気がする。
Avatar
omochimetaru 9/24/2021 5:42 AM
As described there, the iterator can choose how it responds to cancellation. The most common behaviors will be either throwing CancellationError or returning nil from the iterator.
AsyncSequence自身はキャンセル要求があったときにエラーを再送するかnilを返すかを選べるらしい
5:42 AM
そうか、ストリームの終了を意味するnilを返す手段があるから
5:42 AM
nothrowであってもキャンセルに即座に連動する事はできるのか
5:42 AM
次の値としてnilをすぐ返せる。
Avatar
task をとっておいて、 VC が解放されたときに明示的にキャンセルはちょっといやだなぁ。まず、 AnyTask がない。 cencels: [() -> Void]task.cancel を保持すれば良い?
Avatar
実は、タイムリーに、ちょうど、このタスクをとっておいてキャンセルするのめんどいなあと思ってたところだったのですw
Avatar
そして cancellables: Set<AnyCancellable> と違って明示的に deinit でキャンセルしないといけない。ので、専用の型(保持する task (か task.cancel )を deinit で全部キャンセル)が必要になる。 (edited)
Avatar
omochimetaru 9/24/2021 5:47 AM
そういう型を自作するのが良さそう
Avatar
Avatar
omochimetaru
Publisher の エラー型がNeverならIteratorがnothrowってSwiftの文法で記述できないですよね (edited)
Publisherの values がエラー型がNeverなら AsyncPublisher を、それ以外は AsyncThrowingPublisher をというように2つあるので、それでなんとかなってると思ってた https://developer.apple.com/documentation/combine/publisher/values-1dm9r https://developer.apple.com/documentation/combine/publisher/values-v7nz
Avatar
Rxと同じ気分になってこういうの作ってましたね class TaskDisposer { var cancells: [() -> ()] = [] deinit { cancells.forEach { $0() } } func add<S, F: Error>(_ task: Task<S, F>) { cancells.append(task.cancel) } } extension Task { func disposed(by disposer: TaskDisposer) { disposer.add(self) } }
Avatar
omochimetaru 9/24/2021 5:47 AM
DisposeBag.add<T>(_ task: Task<T>)
5:48 AM
Fも消さないと駄目か。↑まさにそれ
Avatar
自作すればいいのはそうなんだけど、単に ObservableObjectobject.willChange を購読するだけで必要になるものが標準で用意されてないのはおかしい。
Avatar
単に ObservableObject の object.willChange を購読する
これって割とレアなんじゃないでしょうかね?
5:49 AM
基本的にはPublished のほうを購読したりしないかな
5:49 AM
でも同じか
Avatar
Avatar
hironytic
Publisherの values がエラー型がNeverなら AsyncPublisher を、それ以外は AsyncThrowingPublisher をというように2つあるので、それでなんとかなってると思ってた https://developer.apple.com/documentation/combine/publisher/values-1dm9r https://developer.apple.com/documentation/combine/publisher/values-v7nz
omochimetaru 9/24/2021 5:49 AM
Combine.AsyncPublisher Combine.AsyncThrowingPublisher なるほど、これなら良さそうですね
Avatar
Avatar
koher
自作すればいいのはそうなんだけど、単に ObservableObjectobject.willChange を購読するだけで必要になるものが標準で用意されてないのはおかしい。
omochimetaru 9/24/2021 5:49 AM
「deinitでキャンセルする」戦略を正解と決めたくなかったからじゃないでしょうか?
5:50 AM
僕はもう一つのアプローチとして、循環参照は許容した上で、
5:50 AM
イベントを起点に解放する戦略がありえると思っています。
Avatar
僕は SwiftUI に寄せて宣言的にコードが書けるように最近は極力 objectWillChange を購読してます。が、いずれにせよどの Publisher を購読しても同じですね。
Avatar
omochimetaru 9/24/2021 5:50 AM
「画面が表示されるときに購読を構築して、画面が消えるときに購読をキャンセルする」みたいな作りにする。
Avatar
ObservableObject は Combine ですよね。だから標準というか、そっちで標準的に用意されているのはAnyCancellableで。。。
Avatar
omochimetaru 9/24/2021 5:51 AM
実際のAPIとして viewDidAppearviewWillDisappear にすると、うまくいかない場合があるみたいな話もあるけど、それはUIKitの問題であって。
Avatar
もうちょっと単純化すると、 viewDidLoadPublisher を購読して変更を View に反映する、 Swift Concurrency 時代の正しいやり方は何なのか、かな。
5:53 AM
↓だと publisher に値が流れてくるまで return しないので、もし VC 解放後に値が流れて来ないならリークする。 override func viewDidLoad() { super.viewDidLoad() Task { [weak self] in guard let publisher = self?.publisher else { return } for await value in publisher.values { guard let self = self else { return } self.label.text = value } } }
Avatar
PassthroughSubject と CurrentValueSubject に相当する使い方ができる AsyncSequence メーカーがあれば、そもそも Combine を使わなくてよくなるのかなあ
5:56 AM
そうでもないか…share()とか考え出したら、Combine相当の別のライブラリになるだけか
Avatar
omochimetaru 9/24/2021 5:58 AM
次のWWDCではこれがベストプラクティスだよって言いながらそのための道具が提供されそう。
😅 1
Avatar
ObservableObject 相当のものは結局必要そうですし、 Concurrency が導入されても簡単には Combine はなくせない?
Avatar
omochimetaru 9/24/2021 5:59 AM
ObservableObject の代わりが AsyncSequence では?
Avatar
objectWillChangePublisher じゃなくしてしまう方法はあるのか。
Avatar
慣れの問題だと思うけど
Avatar
Avatar
omochimetaru
ObservableObject の代わりが AsyncSequence では?
AsyncSequencePublisher の代わりにしかならないんじゃない?
6:01 AM
ちがうか。
Avatar
オペレーター欲しいなら増やせばokです
6:02 AM
その二つは概念的に等しい
Avatar
makeIterator で得られるものが Publisher か。
6:02 AM
やっぱ違うな。
Avatar
omochimetaru 9/24/2021 6:03 AM
ObservableObject は抱えてる @Publisher の変更を通知する機能か。
6:03 AM
それは何かしら実装が必要ですね。
Avatar
AsyncSequencePublisher で、 ObservableObjectPublisher を返す型だから。
Avatar
あ、どうせCombine使うなら、AnyCancellable { task.cancel() } を作って、普通に Set<AnyCancellable> にストアしたらいいのか
Avatar
Avatar
hironytic
あ、どうせCombine使うなら、AnyCancellable { task.cancel() } を作って、普通に Set<AnyCancellable> にストアしたらいいのか
omochimetaru 9/24/2021 6:04 AM
Set<AnyCancellable> に task を insert できるオーバーロードをたせそう。
Avatar
extension Task { func store(in set: inout Set<AnyCancellable>) { set.insert(AnyCancellable { cancel() }) } }
Avatar
と言うかキャンセルだけならシンプルに[()->Void]でいいよ
6:05 AM
.cancelを持たせれば良い (edited)
Avatar
Avatar
tarunon
と言うかキャンセルだけならシンプルに[()->Void]でいいよ
omochimetaru 9/24/2021 6:06 AM
それだとdeinit時にcancelする動作が実装できないよ
Avatar
classの中に持たせるストレージの話だよ
Avatar
まず、 Publisher.valuesTask がキャンセルされた場合に即時 nil を流してくれるんだろうか? (edited)
Avatar
Avatar
tarunon
classの中に持たせるストレージの話だよ
omochimetaru 9/24/2021 6:08 AM
Set<AnyCancellable> ならdeinit cancel挙動がもうついてるからそれを再利用すると楽という話では
Avatar
ああ、なるほどね
Avatar
Avatar
omochimetaru
それだとdeinit時にcancelする動作が実装できないよ
AnyCancellabledeinit 時に cancel を呼ぶので大丈夫では。
Avatar
Avatar
koher
AnyCancellabledeinit 時に cancel を呼ぶので大丈夫では。
omochimetaru 9/24/2021 6:09 AM
[()->Void] だと呼ばれないですよね
Avatar
呼ばれそうな気がする
Avatar
ああ、ひろんさんにリプしてるのかと勘違いした。
Avatar
AnyCancellable.cancelがキャプチャされて解放されなくなるだから、成り立つんじゃないかしら
6:10 AM
まあTaskはキャンセルされないから、結局呼ばなきゃだけど
Avatar
たぶん全員同じことを言ってるのが混乱してるだけに見えてきたww
Avatar
omochimetaru 9/24/2021 6:11 AM
関数の呼び出しをcancelに対応付けるんじゃなくて関数がキャプチャするだけでその関数が死ぬときにAnyCancellableが解放されることを利用するって言ってるのか。
6:12 AM
その場合はtaskを直接キャプチャしたら駄目だから、ミスしそう。
Avatar
無理矢理Combine噛ませるよりは、両方共通して使うための構造を1個作ってそれを使った方が、良いと思うけどね
Avatar
omochimetaru 9/24/2021 6:13 AM
それはそう思う。
6:13 AM
でもCombineでたくさんコード書いたプロジェクトに段階的に導入するとかなら
6:13 AM
いったん Set<AnyCancellable> に寄せておくのが楽とかはありそう
Avatar
それこそ導入したところから共通層入れていくのが良さそうだけど
Avatar
omochimetaru 9/24/2021 6:14 AM
なるほど
Avatar
うーん、いずれにせよ標準で用意されていない道具を使うと、標準で出てきたときに置き換えないといけないんだよなぁ。
Avatar
Avatar
tarunon
無理矢理Combine噛ませるよりは、両方共通して使うための構造を1個作ってそれを使った方が、良いと思うけどね
それはそうですね。AnyCancellable をかますやつは、どっちかというと、koherさんの↓に対する解決策ですね。 https://discord.com/channels/291054398077927425/291054454793306112/890837087148982293
Avatar
なんとか今提供されている道具だけで手軽にできないのかなぁ。
Avatar
AnyCancellable でいいじゃないですか>今提供されている道具
Avatar
TaskGroupは使えないんだっけ、これは並行計算のためのものか
Avatar
Avatar
hironytic
AnyCancellable でいいじゃないですか>今提供されている道具
Taskextension 書かないと面倒じゃないですか?
Avatar
まあでもCombineのCancelableをdeinitしたらキャンセルされちゃうよりは、キャンセルを明示的にやらなければキャンセルしない、の方が理にかなってるな
6:17 AM
まとめてキャンセルしたいときはdeinitを持ったBagを作るだけで良いのだから
6:17 AM
キャンセルしたくないヤツが手軽になる方が利点が大きい
Avatar
Avatar
tarunon
まあでもCombineのCancelableをdeinitしたらキャンセルされちゃうよりは、キャンセルを明示的にやらなければキャンセルしない、の方が理にかなってるな
omochimetaru 9/24/2021 6:18 AM
自分はそう思っててRxSwiftの設計のほうがCombineより良く出来てると思ってる
6:18 AM
キャンセルするインターフェースと、deinitでキャンセルする機能が分離されていて、ユーザーに委ねられている方が綺麗に見える。
Avatar
Avatar
hironytic
そうですが、こういう道具を作り込むと後で全部置き換えないといけなくなるので、まだ Concurrency について色々わかってない中で本当にもっといい方法はないのかな?と。
Avatar
omochimetaru 9/24/2021 6:19 AM
このへんはConcurrencyの機能じゃなくて、その上でどういうパターンでアプリケーションを実装するかというフレームワークの層の話だから、まだ提供されてないんじゃないだろうか
Avatar
Publisher.values を提供したのにそっちを提供してないのおかしくない?
Avatar
omochimetaru 9/24/2021 6:20 AM
まずConcurrencyだけでもパラダイムが大きく変わるから、その上でどういうフレームワークがいいのかはコミュニティが正解を見つけるのを待ったほうがいいというか。
Avatar
Avatar
koher
Publisher.values を提供したのにそっちを提供してないのおかしくない?
omochimetaru 9/24/2021 6:20 AM
.values の部分はどんなフレームワークにするにせよ自明だから良いと思います。
6:20 AM
残りの部分は自分で考えてねってなってるだけ。
Avatar
元々の話は、これまで行われていたような、↓のようなコードすら Swift Concurrency の元では正しくないんじゃないかという話で、 override func viewDidLoad() { super.viewDidLoad() state .objectWillChange .receive(on: DispatchQueue.main) .sink { [weak self] _ in guard let self = self else { return } self.label.text = state.user.name } .store(in: &cancellables) }
6:24 AM
またわかんなくなってきたな。一体このコードは Swift 6 でどう扱われることになるんだろう?
6:24 AM
脱法コードとして有効なまま?警告?エラー?
Avatar
omochimetaru 9/24/2021 6:24 AM
そのへんの会話はちゃんと追ってないんですけど
Avatar
sink@Sendable でない @escaping なクロージャだから actor-isolated なはずで
Avatar
omochimetaru 9/24/2021 6:25 AM
完成した世界なら、sinkに渡してるクロージャが、viewDidLoadのactor contextを引き継ぐんじゃ?
Avatar
でもスレッドスイッチできるからヤバイと。
Avatar
sink は @Sendable でない @escaping なクロージャだから actor-isolated なはずで
これが過渡期における脱法行為なので
6:25 AM
Sendableに整理されると思います
Avatar
Avatar
omochimetaru
完成した世界なら、sinkに渡してるクロージャが、viewDidLoadのactor contextを引き継ぐんじゃ?
もし receive(on: DispatchQueue.global()) するとどうなる?それでも sink の中は MainActor
Avatar
完成した世界では sendable なしにスレッドスイッチはできないのでは
Avatar
Avatar
koher
もし receive(on: DispatchQueue.global()) するとどうなる?それでも sink の中は MainActor
omochimetaru 9/24/2021 6:26 AM
引き継いでるactorに投入されるクロージャに暗黙変換されるのかなと思ってました。
Avatar
だから、 receive(on:) とはそもそも相容れないからどうするんだろ・・・でもそこ(Combine)はswiftの外なんですよね。一応。
Avatar
omochimetaru 9/24/2021 6:27 AM
だから、Combineとしてはglobal queueで実行するけど、この関数が自分で即座にmain actorに投入するから
Avatar
今のSendableがついてないクロージャ渡し、!やtry!がそこら中についてるのと一緒ですよ (edited)
Avatar
omochimetaru 9/24/2021 6:27 AM
.sink { DispatchQueue.main.async { 本文 } } ↑このコードのような挙動をする (edited)
Avatar
Avatar
hironytic
だから、 receive(on:) とはそもそも相容れないからどうするんだろ・・・でもそこ(Combine)はswiftの外なんですよね。一応。
Swift の外としても、違法として破壊的にエラーにしてしまうのか、脱法として穴を残すのか、
Avatar
omochimetaru 9/24/2021 6:27 AM
と思ってた
6:28 AM
あーでもそれはありえないか
6:28 AM
返り値がある関数だったら成り立たない話になるな
Avatar
結局どうしようもなくって、脱法マーカーが出来るんだと思いますよ
6:29 AM
@UnsafeNonSendable みたいなのが生まれる
Avatar
omochimetaru 9/24/2021 6:29 AM
じゃあActor Contextの引き継ぎって何を意味してるんだ?あくまで静的解析の話なのかな
Avatar
それはたぶんループしてるので、おもちさんに午前の会話を眺めてもらう方が話がはやそうww
Avatar
Avatar
omochimetaru
じゃあActor Contextの引き継ぎって何を意味してるんだ?あくまで静的解析の話なのかな
すくなくとも、 // Actor foo Task { // ここも Actor foo の中 } これはやってくれるはず。
6:31 AM
@Sendable クロージャは context の引き継ぎをぶった切る。
Avatar
Avatar
hironytic
それはたぶんループしてるので、おもちさんに午前の会話を眺めてもらう方が話がはやそうww
omochimetaru 9/24/2021 6:31 AM
今北産業
Avatar
Sendableの言語仕様って、「俺のアクター」「お前のアクター」しかやってなくて (edited)
Avatar
@nonescaping なクロージャは context を引き継ぐ。
6:31 AM
問題は @Sendable でない @escaping なクロージャがよくわからん・・・。
Avatar
そこに第三勢力としてアクターじゃ無いですってのが混ざってるんだからそりゃ無理って話
6:32 AM
@Sendable でない @escaping なクロージャ 今のところこれは90%ぐらい脱法です
Avatar
Avatar
tarunon
@Sendable でない @escaping なクロージャ 今のところこれは90%ぐらい脱法です
omochimetaru 9/24/2021 6:32 AM
@Sendable を付けることでセーフティが導入されるけど、付けない場合は旧世界のガバガバ挙動しかないってこと?
Avatar
そうだよ
Avatar
omochimetaru 9/24/2021 6:32 AM
ほ〜ん
6:33 AM
ObjCの IUO みたいな感じか
Avatar
付けない場合は、「完成された安全なところ」と「旧世界ガバガバ危険地帯」が混ざってる
Avatar
@Sendable でない @escaping なクロージャもcontextを引き継ぐ、と、コンパイラは思っているが、言語の外でランタイムにスレッドスイッチできてしまうことにより脱法が可能になっている
Avatar
だから安全になったマーカーか脱法マーカーが欲しい
Avatar
omochimetaru 9/24/2021 6:33 AM
脱法マーカーに関しては
6:33 AM
@propertyWrapper struct UnsafeSendable
6:33 AM
これつくって
6:34 AM
見かけ上Sendableだけどその上で @UnsafeSendable var foo
6:34 AM
ゴリ押しするスタイルがいいんじゃない。
Avatar
Avatar
omochimetaru
今北産業
現状で↓のような挙動をするんだけど、 Task { }MainActor を引き継いで見えることで混乱して色々話したけど、これ自体仕様じゃないっぽいという話をしてた。 final class ViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // (1) メインスレッド DispatchQueue.global().async { // (2) 別のスレッド Task { // (3) メインスレッド } } } } (edited)
Avatar
クロージャ渡しに関しては以下の通り。 なし -> 合法 @Sendable -> 合法 @escaping -> 脱法だが稀に合法 @Sendable @escaping -> 合法 (edited)
Avatar
Avatar
koher
現状で↓のような挙動をするんだけど、 Task { }MainActor を引き継いで見えることで混乱して色々話したけど、これ自体仕様じゃないっぽいという話をしてた。 final class ViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // (1) メインスレッド DispatchQueue.global().async { // (2) 別のスレッド Task { // (3) メインスレッド } } } } (edited)
omochimetaru 9/24/2021 6:35 AM
その挙動すごいですね。どうやって実現されてるの・・・
Avatar
Avatar
koher
現状で↓のような挙動をするんだけど、 Task { }MainActor を引き継いで見えることで混乱して色々話したけど、これ自体仕様じゃないっぽいという話をしてた。 final class ViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // (1) メインスレッド DispatchQueue.global().async { // (2) 別のスレッド Task { // (3) メインスレッド } } } } (edited)
それに関しては、いまのところ結局、↓という挙動かなと思ってます。 https://discord.com/channels/291054398077927425/291054454793306112/890807721052479529
Avatar
現状の実装も正しくないから、結局想定されている正しい仕様が何なのかわからない・・・。
Avatar
Avatar
hironytic
それに関しては、いまのところ結局、↓という挙動かなと思ってます。 https://discord.com/channels/291054398077927425/291054454793306112/890807721052479529
omochimetaru 9/24/2021 6:36 AM
解釈は僕もそう思うんですけど、実際問題mainへの投入はどうやって実装されているのか?
Avatar
そのまま継続せずに新しくMainActorのキューに積むとmainへの投入になるということじゃないかと。
Avatar
omochimetaru 9/24/2021 6:38 AM
Task.init が MainActor をどうやって持ってくるのか
Avatar
そこは実行時じゃなくて静的に、外側のアクターを引き継ぐ。
Avatar
omochimetaru 9/24/2021 6:39 AM
Effectively, when the closure is called, it will immediately "hop" over to the actor's context so that it runs within the actor.
Avatar
Avatar
hironytic
そこは実行時じゃなくて静的に、外側のアクターを引き継ぐ。
omochimetaru 9/24/2021 6:41 AM
コード生成されてるってことですか?
6:41 AM
Task.init だけ、コンパイラが特別に配慮して、静的に対応付けられたMainActorのインスタンス?を注入する? (edited)
Avatar
よくわからないけど、まず、さっきの Task の中身は、メインスレッドで実行されるときと、別スレッドで実行されるときの両方が確認されていて、
Avatar
omochimetaru 9/24/2021 6:41 AM
それともcurrent actorみたいな秘密の変数があるのかな。
Avatar
↓によると @escaping な( @Sendable でない)クロージャは actor-isolated 扱いになっていて、でも検査されていなくて危険と。なので、実際には↑の (2)MainActor に投入されてないけど、 MainActor とコンパイラは思ってる? https://discord.com/channels/291054398077927425/291054454793306112/890513245801160744 (edited)
6:42 AM
そう考えると、 (1) から (2) へ、 (2) から (3)MainActor が引き継がれるとも考えられる。
Avatar
Avatar
hironytic
よくわからないけど、まず、さっきの Task の中身は、メインスレッドで実行されるときと、別スレッドで実行されるときの両方が確認されていて、
omochimetaru 9/24/2021 6:42 AM
同じコードでも(3)の結果が変動するってことですか?
Avatar
いや、コードの書き方によって、ですね。えーとshizさんの
Avatar
Avatar
omochimetaru
同じコードでも(3)の結果が変動するってことですか?
viewDidLoad の中を別の @MainActor な関数に切り出すと挙動が変わる。
6:44 AM
ヤバいな。なんだそりゃ。
6:45 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
6:45 AM
@available(SwiftStdlib 5.5, *) @frozen public struct Task<Success: Sendable, Failure: Error>: Sendable { @usableFromInline internal let _task: Builtin.NativeObject @_alwaysEmitIntoClient internal init(_ task: Builtin.NativeObject) { self._task = task } }
6:45 AM
Task.init はマジでコンパイラが特別扱いしてそうな見た目をしてるな。
Avatar
だから、コンパイラとしては、(1) から (2) へ、(2) から (3) へ、全部MainActorだと思っていて、(2) が終わったあと、そのままそのスレッドで継続して (3) を実行するコードを吐いてもいいし、(3) は改めてMainActorのキューにのせるコードを吐いてもいいんじゃないかと。
Avatar
Avatar
omochimetaru
なるほど
それ見て結局何が正しいのかわからんってなってる。想定されている仕様が何なのか。それに対する一つの仮説が tarunon さんの脱法の整理。
Avatar
本来ならばDispatchQueueとかCombineのクロージャは @escaping @Sendable なはずだけど、過渡期に置いてこれを宣言できないので、整理されず @escaping だけになっている、という考え方です
Avatar
コンパイラは (2) が MainActor で実行されるものだと思ってるのに、ランタイムで (2) を別のスレッドで実行できちゃっているから、(3) の挙動が安定しないのかなと思ってます。この (2) を脱法と呼んでます
Avatar
Avatar
hironytic
だから、コンパイラとしては、(1) から (2) へ、(2) から (3) へ、全部MainActorだと思っていて、(2) が終わったあと、そのままそのスレッドで継続して (3) を実行するコードを吐いてもいいし、(3) は改めてMainActorのキューにのせるコードを吐いてもいいんじゃないかと。
でもこれが想定仕様だとすると、 (2) は将来 MainActor に投入されるようになる?↓だし。
This is in line with the long term plan for actor isolation, but opens up some holes in the short term because Sendable closures are not enforced throughout the Swift ecosystem.
6:47 AM
public init( priority: TaskPriority? = nil, @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> Success ) {
Avatar
結局 Task.init の actor context の引き継ぎとはこの @_inheritActorContext の挙動は何なのかって話になってて、コンパイラがこれをどう扱ってるかを追うとわかるのかも。
Avatar
omochimetaru 9/24/2021 6:48 AM
_inheritActorContext の取り扱いで魔法がかかってそうですね
Avatar
ただ、それでわかるのは結局今の実装がどうなってるかで、想定仕様が何かはわからない。
Avatar
omochimetaru 9/24/2021 6:49 AM
想定仕様はproposalに書いてある範囲ですよね。
Avatar
Avatar
omochimetaru
_inheritActorContext の取り扱いで魔法がかかってそうですね
それについては昨日、家庭さんが話としては出してきてた(魔法の中身はわからない) https://discord.com/channels/291054398077927425/291054454793306112/890416523825537064
Avatar
Avatar
omochimetaru
想定仕様はproposalに書いてある範囲ですよね。
@escaping なクロージャのことほとんど書いてなくない?
Avatar
書いてないというか、 @Sendable なクロージャだけが non-isolated で、他は @escaping も含めて isolated だと思うんだけどなあ。書いてないだけに。 (edited)
Avatar
Avatar
hironytic
書いてないというか、 @Sendable なクロージャだけが non-isolated で、他は @escaping も含めて isolated だと思うんだけどなあ。書いてないだけに。 (edited)
Escaping closures can now be actor-isolated; only @Sendable prevents isolation.
なので actor-isolated はそうだと思います。
Avatar
omochimetaru 9/24/2021 6:52 AM
ふむふむ
Avatar
で、これが
This ... opens up some holes in the short term
はその通りとして
Avatar
今の扱いはこうなってそう なし -> 合法 (isolated) @Sendable -> 合法 (non-isolated) @escaping -> 脱法 (non-isolated) @Sendable @escaping -> 合法 (non-isolated)
Avatar
This is in line with the long term plan for actor isolation
なのはどういう想定なんだろう?
6:53 AM
将来的には安全になるってこと?
Avatar
Avatar
tarunon
今の扱いはこうなってそう なし -> 合法 (isolated) @Sendable -> 合法 (non-isolated) @escaping -> 脱法 (non-isolated) @Sendable @escaping -> 合法 (non-isolated)
omochimetaru 9/24/2021 6:54 AM
(1)が合法なのはそもそもコンテキストスイッチをまたぎようがないからってことよね
Avatar
そうだね
Avatar
Avatar
tarunon
今の扱いはこうなってそう なし -> 合法 (isolated) @Sendable -> 合法 (non-isolated) @escaping -> 脱法 (non-isolated) @Sendable @escaping -> 合法 (non-isolated)
その脱法の部分は、コンパイラは isolated としてる気がする。そのままMainActorのメソッドをawaitなしに呼べるので。
Avatar
えーと、もうちょっと誤解のないように書くと
6:55 AM
@escapingは新世界と旧世界の両方から自分にとって都合のいいように見えています
Avatar
omochimetaru 9/24/2021 6:55 AM
このパッチのテストケースがまさにわかりやすいですね。
Avatar
たまに両方にとっての合法な使われ方(UIView.animateなど)をしている場合がありますが、それは例外で
6:56 AM
ほとんどが DispatchQueueとかCombine のような違法コードになっている
Avatar
omochimetaru 9/24/2021 6:56 AM
コメントの書き換えが明確に犯罪予告してる
Avatar
Avatar
omochimetaru
コメントの書き換えが明確に犯罪予告してる
こう変化したのはわかるし、右のコードが現状で危険なのはわかるんだけど、将来的にどう解決するつもりなのか(解決されないのか)がわからない。最初に omochimetaru の言ってたように強制的に MainActor 投入されるようになるのかもしれないし。
Avatar
Avatar
koher
こう変化したのはわかるし、右のコードが現状で危険なのはわかるんだけど、将来的にどう解決するつもりなのか(解決されないのか)がわからない。最初に omochimetaru の言ってたように強制的に MainActor 投入されるようになるのかもしれないし。
omochimetaru 9/24/2021 6:58 AM
強制投入は返り値を持って帰れないから無理ですね
Avatar
ブロッキングになっちゃうかぁ。
6:59 AM
async にするわけにもいかないしなぁ。
Avatar
omochimetaru 9/24/2021 7:00 AM
解決方法は難しいですね。
7:00 AM
安全性を達成するには下位互換ぶっ壊して違法認定するしかないけど
7:00 AM
逆に誰もDispatchQueueを使わなくなれば違法のままでも問題が起こらないようにできるかな?
Avatar
そうすると
This is in line with the long term plan for actor isolation, but opens up some holes in the short term
の long term はどう考えてるの?将来みんながこの API を使わなくなったら安全ってこと?
Avatar
脱法マーカー付けて締め付けていくのが良いと思いますけどね
7:01 AM
@escapingなんて普通にSwift書いてそこら中に出てくるので、これが脱法状態になってるのはマズい
Avatar
Avatar
koher
そうすると
This is in line with the long term plan for actor isolation, but opens up some holes in the short term
の long term はどう考えてるの?将来みんながこの API を使わなくなったら安全ってこと?
omochimetaru 9/24/2021 7:02 AM
昔フォーラムで、Swift5から6の間に警告期間を設けて6では徹底する、みたいなコアチームの意見は見ましたね
Avatar
Avatar
omochimetaru
昔フォーラムで、Swift5から6の間に警告期間を設けて6では徹底する、みたいなコアチームの意見は見ましたね
Avatar
for awaitやめてasyncSequence.map使ったらActor跨いで書き込めます!とか記事がQiitaに出てきた日には白目ひん剥いて倒れると思う
Avatar
Avatar
omochimetaru
昔フォーラムで、Swift5から6の間に警告期間を設けて6では徹底する、みたいなコアチームの意見は見ましたね
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/nnnn-sendable-staging.md at sendable-staging · DougGregor/swift-evolution
Avatar
omochimetaru 9/24/2021 7:04 AM
家庭先生が全部回答してた
Avatar
omochimetaru 9/24/2021 7:04 AM
あ!これですこれです。フォーラムじゃなくて文書か。
Avatar
でも Swift 6 で違法になるってどういうことだろう? @escaping も non-isolated に戻すってことかな?
7:05 AM
↑のドラフトに書いてあるのかな?
Avatar
omochimetaru 9/24/2021 7:06 AM
はい、僕はそういう意味で書いてます。
7:06 AM
単純に考えて、@escaping は言葉通りエスケープするのでどこから実行される事もありえるわけだから
7:06 AM
non-isolated でしかありえないわけで、
7:07 AM
なので暗黙に @Sendable がついてくるんじゃないか。
Avatar
有り得ないことはないんだよな
Avatar
omochimetaru 9/24/2021 7:07 AM
isolationを担保できなくない?
7:07 AM
さっき書いたように、返り値があるから。
7:07 AM
あ、async 関数なら、暗黙actor投入をすることができるか。 (edited)
Avatar
その方向は違法マーカーよりは望ましいと思うけど、 Proposal の
Escaping closures can now be actor-isolated; only @Sendable prevents isolation.
は暫定措置ってことなのかなぁ。
Avatar
UIView.animateとかがそうだし、AsyncStreamのcontinuation.onTerminationもこれ実質escaping かつ Sendableじゃないか (edited)
Avatar
omochimetaru 9/24/2021 7:09 AM
UIview.animateの安全性は型からはいえなくて実際の実装が安全ってだけだから、 @UnsafeUncheckedIsolated みたいな
7:09 AM
マーカーを付けるんじゃない。
Avatar
Avatar
koher
その方向は違法マーカーよりは望ましいと思うけど、 Proposal の
Escaping closures can now be actor-isolated; only @Sendable prevents isolation.
は暫定措置ってことなのかなぁ。
omochimetaru 9/24/2021 7:09 AM
その差分が出たときのフォーラムのアナウンスに書いてないかしら
7:10 AM
Changes in the second reviewed proposal:
7:10 AM
2版でこんな重大なトピックが出てたのか。
Avatar
Avatar
omochimetaru
なので暗黙に @Sendable がついてくるんじゃないか。
これ( @Sendable でない @escaping なクロージャ)は単に後から実行する単純な計算とかもあるんじゃない? (Int) -> Int みたいな。計算を DI するような場合とか。
Avatar
omochimetaru 9/24/2021 7:11 AM
2回めのレビュー後だから3版か?
Avatar
Avatar
koher
これ( @Sendable でない @escaping なクロージャ)は単に後から実行する単純な計算とかもあるんじゃない? (Int) -> Int みたいな。計算を DI するような場合とか。
omochimetaru 9/24/2021 7:11 AM
単純な計算なら @Sendable チェックを突破したらいいのでは
7:12 AM
クロージャ実装側が { $0 + $1 } とか書いてるだけなら、 @Sendable になってても別に困らない
Avatar
The rule about @escaping closures being non-isolated was never great: it's always been an heuristic to try to deal with the world where @Sendable has yet to be fully adopted. So instead of making this heuristic part of the actors design, to be removed at some later point, we've removed it from the proposal. Instead, we'll need to rely on dynamic checking where actor code interacts with non-@Sendable`-enforcing code.
https://forums.swift.org/t/se-0306-second-review-actors/47291/4
There was a little feedback here, but not a lot of discussion. The rule about @escaping closures being non-isolated was never great: it's always been an heuristic to try to deal with the world where @Sendable has yet to be fully adopted. So instead of making this heuristic part of the actors design, to be removed at some later point, we've remov...
Avatar
Avatar
omochimetaru
クロージャ実装側が { $0 + $1 } とか書いてるだけなら、 @Sendable になってても別に困らない
サードパーティライブラリの型を使っていて、その型が Sendable に適合してないとかあると面倒そう。
Avatar
omochimetaru 9/24/2021 7:13 AM
そういうときは自己責任でさっきかいた @UnsafeSendable を使うしかないですね
Avatar
サードパーティライブラリの型を使っていて、その型が Sendable に適合してないとかあると面倒そう。
これがその文書で提案されようとしている@unsafeSendableに該当しますかね? The @unsafeSendable attribute indicates that the corresponding parameter (of function type) is intended to be @Sendable going forward. For a client that has not yet adopted concurrency, it will be treated as a non-@Sendable function type. https://github.com/DougGregor/swift-evolution/blob/sendable-staging/proposals/nnnn-sendable-staging.md#supporting-clients-that-predate-concurrency
(edited)
Avatar
Avatar
shiz
サードパーティライブラリの型を使っていて、その型が Sendable に適合してないとかあると面倒そう。
これがその文書で提案されようとしている@unsafeSendableに該当しますかね? The @unsafeSendable attribute indicates that the corresponding parameter (of function type) is intended to be @Sendable going forward. For a client that has not yet adopted concurrency, it will be treated as a non-@Sendable function type. https://github.com/DougGregor/swift-evolution/blob/sendable-staging/proposals/nnnn-sendable-staging.md#supporting-clients-that-predate-concurrency
(edited)
omochimetaru 9/24/2021 7:14 AM
おお。言語機能としての提供が議論されているのか
Avatar
Avatar
shiz
The rule about @escaping closures being non-isolated was never great: it's always been an heuristic to try to deal with the world where @Sendable has yet to be fully adopted. So instead of making this heuristic part of the actors design, to be removed at some later point, we've removed it from the proposal. Instead, we'll need to rely on dynamic checking where actor code interacts with non-@Sendable`-enforcing code.
https://forums.swift.org/t/se-0306-second-review-actors/47291/4
omochimetaru 9/24/2021 7:16 AM
Sendableが普及するまでの処置で、良くないねって言ってますね。
7:17 AM
プロポーザルからはこの部分を除去して、代わりに実行時のチェックに頼る必要があるだろう。
Avatar
英語むずくない?細かい部分がよくわからん・・・。
7:19 AM
The rule about @escaping closures being non-isolated was never great:
@escaping クロージャが non-isolated になるルールははまったく良くなかった。
Avatar
omochimetaru 9/24/2021 7:20 AM
non-isolatedなのが古い提案で、この審査で、それをやめた(違法コードを許すようにした)から、そうですね (edited)
7:20 AM
never greatは過去の提案を否定してるだけか。読み違えてた。
7:20 AM
その次の文が大事だと思ってて、
Avatar
it's always been an heuristic to try to deal with the world where @Sendable has yet to be fully adopted.
つまり、それは常に、 @Sendable が完全に採用されるまでの世界を扱うためのヒューリスティックだ。
Avatar
omochimetaru 9/24/2021 7:22 AM
これ、「hueristic」が指す仕様がもともとあって、提案から削除されてるんじゃないですかね (edited)
7:22 AM
escaping closureの場合の特殊なルールが(単純に常にnon-isolatedにするわけではないもの?) (edited)
7:22 AM
いろいろ書いてあったんだけど全部やめたよっと。
Avatar
So instead of making this heuristic part of the actors design, to be removed at some later point, we've removed it from the proposal.
だから、このヒューリスティックを actor の設計の一部とする代わりに、将来のどこかで除去されるものだし、プロポーザルから削除した。
Avatar
Avatar
omochimetaru
いろいろ書いてあったんだけど全部やめたよっと。
削除されたのは @escaping クロージャが non-isolated になることじゃない?
Avatar
omochimetaru 9/24/2021 7:24 AM
diffみてみましょうか
7:24 AM
なんか長い話があった気もしてきたんですよね
7:24 AM
この古い版を読んだ気がする
Avatar
確かescapingなものは全部Sendableと見なすが元々だったような...🤔 あ、これだ。
If the closure is @escaping or is nested within an @escaping closure or a local function, it is non-isolated.
で、これに対してラトナーさんから反対の意見が出ていました https://forums.swift.org/t/se-0306-actors/45734/4
(edited)
Avatar
omochimetaru 9/24/2021 7:25 AM
This rule was a hack to try to interoperate with existing Swift code that doesn't understand Sendable. We'll have to deal with this in a different way.
Avatar
Instead, we'll need to rely on dynamic checking where actor code interacts with non-@Sendable`-enforcing code.
代わりに、 actor のコードが @Sendable であることが強制されていないコードと interact するところでは、動的検査に頼る必要があるだろう。
Avatar
@escaping なクロージャーは non-isolated だよね」というのが、完成された世界では成り立たないんじゃね?ということで、その仕様はやめたということなのか。
Avatar
うーん、 DispatchQueueasync みたいなスレッドスイッチしちゃうヤバイ @escaping クロージャは将来的に誰も使わなくなるから、それらのために @escaping クロージャを non-isolated にしてると不便だよね(さっきの単純な計算を注入した後から使う例とか)、だからプロポーザルから取り除いて @escaping クロージャも isolated 扱いにしたけど、現状は DispatchQueueasync みたいなやつもいるから危険だよ、ってこと?
Avatar
omochimetaru 9/24/2021 7:32 AM
> **Rationale**: In theory, `@escaping` is completely orthogonal to `@Sendable`, and a Swift program built entirely with `@Sendable` from the ground up would not have the rule that `@escaping` closures be non-isolated. However, the existing Swift ecosystem is built without `@Sendable`, which leaves us with an unfortunate choice. We can assume that the lack of `@Sendable` on a function type means that the closure won't escape the concurrency domain, and where existing code (i.e., all Swift code that's been written so far) breaks this assumption, we'll have a data race. Or, we can conservatively assume that all existing function types are `@Sendable`, which will prevent all data races, but at the cost of being unable to use even the most basic facilities (such as `Sequence.map`, above). Therefore, we employ an heuristic: `@escaping` is a good (but imperfect) indicator in Swift today that the closure can be executed concurrently, so we don't permit escaping closures to be actor-isolated. This eliminates a significant proportion of the data races that would affect actor state, and the cost of (1) admitting some data races with existing code that manages to execute a closure concurrently without escaping it, and (2) prohibiting some safe patterns where a closure escapes but does not cross concurrency domains. This is a pragmatic, temporarily solution to the problem of rolling out data-race prevention throughout an existing ecosystem. Our approach will ratchet up the safety as code opts in to more concurrency safety in future language versions.
7:35 AM
「理論上は、escapingとsendableは直行する概念だけど、まだsendableが普及してないから妥協をする必要があって、実際escapingはコールバックに使ってることが多いし、escapingならnon-isolated(=sendable)にするヒューリスティックにしようと思うよ」
7:35 AM
みたいな事が書いてあって
7:35 AM
それに対してラトナーが↑で
7:35 AM
「いやいやそれだとマズイでしょ理論上直行するわけで・・・(以下説明)」みたいなツッコミをした結果
7:36 AM
第二回レビューのタイミングでは、escapingに関するヒューリスティック(=sendable)が取り除かれた?
7:37 AM
ラトナー
and it makes perfect sense for a closure to be @escaping without being @Sendable.
7:37 AM
Sendableじゃないけどescapingなクロージャは完全に正しい(ありえる)
Avatar
やっぱ、完成した世界ではそもそも @escaping かつ non- @Sendable なクロージャが危険な振る舞いをすること自体があり得ないってことなんだろうな。
Avatar
完成された世界では、スレッドスイッチするのはactorだけであって、actor境界をまたぐときはsendableでないといけない。もし、sendableでない escaping クロージャをメンバに持つ型があったら、その型は sendable にはなれないはず?そうするとその型が actor 境界をまたぐことはないので、問題は発生しない?
Avatar
omochimetaru 9/24/2021 7:39 AM
完成された世界がActorだけの世界を言うのか、DispatchQueue等があっても検査と文法で上手いことやれるのかのどっちだ
Avatar
Avatar
hironytic
完成された世界では、スレッドスイッチするのはactorだけであって、actor境界をまたぐときはsendableでないといけない。もし、sendableでない escaping クロージャをメンバに持つ型があったら、その型は sendable にはなれないはず?そうするとその型が actor 境界をまたぐことはないので、問題は発生しない?
@Sendable でない @escaping なクロージャを呼び出すときは actor context を引き継いでも問題のないコードしか存在しない、ってことじゃないでしょうか。
👌 1
Avatar
Avatar
omochimetaru
完成された世界がActorだけの世界を言うのか、DispatchQueue等があっても検査と文法で上手いことやれるのかのどっちだ
DispatchQueueasync 等の壊せる API が( deprecated を経て)取り除かれるか、 async 等に @Sendable が付与されるかかなぁ。 (edited)
7:41 AM
Swift の世界からは壊せなくなると。
7:41 AM
他言語連携してスレッド使ってとかやったら壊せるんだろうけど。 (edited)
Avatar
Avatar
koher
DispatchQueueasync 等の壊せる API が( deprecated を経て)取り除かれるか、 async 等に @Sendable が付与されるかかなぁ。 (edited)
omochimetaru 9/24/2021 7:44 AM
例えば UIView.animate の受け取るクロージャは、定義側が @MainActor @escaping () -> Void になってればうまくいくんですかね?
Avatar
それはうまくいきそうだ
Avatar
@MainActor のときは問題なさそうだけど、他の actor の context で呼び出されたらどうなるんだ??
Avatar
omochimetaru 9/24/2021 7:46 AM
利用側が他のActorのcontextの場合、クロージャを定義するところでSendableなものしかキャプチャできなくなるのかな?
Avatar
あーそうか
Avatar
他の actor の context で呼び出すのが無理なのでは
Avatar
omochimetaru 9/24/2021 7:46 AM
(そもそもanimateを呼び出せないけど
Avatar
全部 await 付けないといけなくなっちゃって、でも async じゃないから何もできないんだ。
Avatar
omochimetaru 9/24/2021 7:48 AM
うーんつまり整理すると
7:48 AM
@escaping のときに Sendable になってなくて脱法に見えるけど
Avatar
UIView.animate(withDurations: 0.5, animations: { self.label.alpha = 1.0 // MainActor でないとこれができない })
Avatar
omochimetaru 9/24/2021 7:48 AM
これは既存APIが脱法実装なのであって、
7:48 AM
言語仕様としては最終的な形として正しいってこと?
Avatar
そもそもUIViewのコンテキストがMainActorだから
7:49 AM
animations, completionもMainActorなら問題ないよ
Avatar
UIView.animate は他の actor context でも呼び出せるけど、 animations に渡すクロージャ式の中で UI コンポーネントに触れないから意味のあることができない。
Avatar
Avatar
tarunon
そもそもUIViewのコンテキストがMainActorだから
MainActor からだと問題ないですが、別の actor から呼び出したときに long term でどう安全になるんだろうと。
Avatar
Avatar
koher
UIView.animate は他の actor context でも呼び出せるけど、 animations に渡すクロージャ式の中で UI コンポーネントに触れないから意味のあることができない。
omochimetaru 9/24/2021 7:50 AM
UIView.animate の呼び出しを含めてまるごと MainActor.run に丸投げするしかないですね
Avatar
他の actor context から、 sendable じゃないクロージャを渡せるんですかね。そもそも。
Avatar
Avatar
hironytic
他の actor context から、 sendable じゃないクロージャを渡せるんですかね。そもそも。
animations@Sendable が付与されるはずってことですか?
Avatar
Avatar
hironytic
他の actor context から、 sendable じゃないクロージャを渡せるんですかね。そもそも。
omochimetaru 9/24/2021 7:50 AM
Actor ContextをまたぐときはSendable closureしか渡せない、というのが良いのでは
Avatar
Sendableなのはその通りだと思いますよ
Avatar
Avatar
omochimetaru
Actor ContextをまたぐときはSendable closureしか渡せない、というのが良いのでは
そう、それが良いと思うので。
Avatar
Avatar
hironytic
そう、それが良いと思うので。
omochimetaru 9/24/2021 7:51 AM
でも、まだそういうルールは整備されてない?ってことかしら
Avatar
↓自体は完全に合法で actor context もまたいでなくないですか? // MainActor でない何かの Actor UIView.animate(withDuration: 0.5, animations: { })
Avatar
Avatar
koher
↓自体は完全に合法で actor context もまたいでなくないですか? // MainActor でない何かの Actor UIView.animate(withDuration: 0.5, animations: { })
omochimetaru 9/24/2021 7:53 AM
僕が思ってる理想の解決方法だと、 animations が、 @MainActor 宣言されているので、 そこで作っているクロージャは MainActor コンテキストになっていて、 作っているコンテキストはotherActorなので、 そのクロージャは@Sendable になるんだけど、 中身が空だからキャプチャが無いのでsendableチェックを突破できて動く。
7:55 AM
あれでも、 @MainActor ってのも変な気がしてきたな。動的なActorのときは同じようなことをどうやればいいんだ。
Avatar
Avatar
omochimetaru
僕が思ってる理想の解決方法だと、 animations が、 @MainActor 宣言されているので、 そこで作っているクロージャは MainActor コンテキストになっていて、 作っているコンテキストはotherActorなので、 そのクロージャは@Sendable になるんだけど、 中身が空だからキャプチャが無いのでsendableチェックを突破できて動く。
それだったら UIView.animate@MainActor が付与されて、 animations@Sendable が強制される、他の Actor から呼ぶときは await 必須、かなぁ。
7:56 AM
await するといってもアニメーションが終わるまで待つんじゃなくて、メインスレッドで発火されるまで suspend 。
Avatar
Avatar
koher
それだったら UIView.animate@MainActor が付与されて、 animations@Sendable が強制される、他の Actor から呼ぶときは await 必須、かなぁ。
omochimetaru 9/24/2021 7:56 AM
それだったら、とは?
7:57 AM
反論されているのか同意されているのかよくわからない
Avatar
Avatar
omochimetaru
それだったら、とは?
animations@MainActor よりも UIView.animate@MainActor がいいかなと。
Avatar
omochimetaru 9/24/2021 7:58 AM
UIView.animate 自体が @MainActor 宣言されると、引数の animations も MainActor外から渡すときはSendableになるからか。
Avatar
はい。
Avatar
omochimetaru 9/24/2021 7:59 AM
どうなんでしょう、もともと UIView.animate が、メイン以外から呼んでも良い仕様なら、
Avatar
Sendableがわからなくなってきた
Avatar
omochimetaru 9/24/2021 7:59 AM
それは仕様をせばめちゃってますよ
Avatar
Avatar
omochimetaru
それは仕様をせばめちゃってますよ
完全な世界を作るのは仕様を狭めるんじゃない?
Avatar
omochimetaru 9/24/2021 8:01 AM
asyncからしか呼べなくなる影響が一番大きいのかな。
Avatar
Avatar
omochimetaru
asyncからしか呼べなくなる影響が一番大きいのかな。
MainActor から呼ぶときは同期的だし、大体問題ないのでは。
Avatar
Avatar
koher
MainActor から呼ぶときは同期的だし、大体問題ないのでは。
omochimetaru 9/24/2021 8:02 AM
処理本体をメインスレッドでやらないスタイルがありえるのかなと思って。
Avatar
どうしても他の Actor から呼ばないといけないときは↓でいいし。 Task { await UIView.animate(...) }
Avatar
omochimetaru 9/24/2021 8:03 AM
アニメーション周りだとミリ秒単位の応答性が気になりそうな気がしてた。
Avatar
今ちょうどアニメーション伴うところでasync await使えねーなってなってるところでした
Avatar
completionasync で受け取るのがいいのかな。
Avatar
view.setNeedsLayout() と viewDidLayoutSubviewsを使ってループさせて、微妙なレンダリング完了の隙間にエフェクトを差し込むみたいなテクニックがあるんですけど、これをasync sequenceを使うように書き換えたらスレッド跨ぐのでちらつきが見えるようになっちゃった
Avatar
// UIView @MainActor class func animate(withDuration duration: TimeInterval, animations: @escaping () -> Void) async -> Bool (edited)
Avatar
AsyncStreamのyieldが全然yieldじゃないw
Avatar
Avatar
tarunon
view.setNeedsLayout() と viewDidLayoutSubviewsを使ってループさせて、微妙なレンダリング完了の隙間にエフェクトを差し込むみたいなテクニックがあるんですけど、これをasync sequenceを使うように書き換えたらスレッド跨ぐのでちらつきが見えるようになっちゃった
omochimetaru 9/24/2021 8:06 AM
UI周りだとやっぱりうかつなawaitはチラつきになるかあ
Avatar
全然だめですね、このあたりはJavaScriptのasync generatorの方が優秀だな
Avatar
動画関係の処理でも、bufferのライフタイムが厳しくてactorのメソッドにbuffer渡すとawaitしてる間にバッファ死んでしまいましたね
Avatar
Taskのpriorityに.realtimeが欲しい
Avatar
Avatar
Iceman
動画関係の処理でも、bufferのライフタイムが厳しくてactorのメソッドにbuffer渡すとawaitしてる間にバッファ死んでしまいましたね
それはコピーが必要そうな・・・。
Avatar
Avatar
Iceman
動画関係の処理でも、bufferのライフタイムが厳しくてactorのメソッドにbuffer渡すとawaitしてる間にバッファ死んでしまいましたね
omochimetaru 9/24/2021 8:07 AM
従来の「あるスレッドでコールバックが呼ばれる」系のAPIは、その呼出の間に同期的に作業を終えないといけない仕様な事が多い
8:07 AM
従来のというかメディア系はだいたいそう
Avatar
既存コードがコピーナシでうごいてるのでコピー避けたくて、結局actorを諦めました😅
Avatar
omochimetaru 9/24/2021 8:08 AM
メディア系だと性能のためにコピーを嫌ってロックで制御してるから。
Avatar
kotlinのrunBlocking相当の操作はあると嬉しいなと思いました
Avatar
Avatar
tarunon
全然だめですね、このあたりはJavaScriptのasync generatorの方が優秀だな
omochimetaru 9/24/2021 8:09 AM
ただまあ、これからはnon-asyncであるか、asyncでもawaitが無ければ同期的だからチラつかない、ということを意識するというだけであって
Avatar
Avatar
Iceman
既存コードがコピーナシでうごいてるのでコピー避けたくて、結局actorを諦めました😅
それだと同期的に処理する必要があるし、 actor は向かないように思います。
Avatar
omochimetaru 9/24/2021 8:09 AM
従来の、コールバックを挟むとチラつくので気をつける、の見た目が変わっただけでは?
8:10 AM
元からあった課題の見た目が変わっただけで課題が増えたわけではないというか。 (edited)
Avatar
課題は増えてないけど、解決を期待したボイラープレートがそのままになっちゃうのは残念ですね
Avatar
課題は増えてないけど見た目が気づきにくい感じになったような
Avatar
omochimetaru 9/24/2021 8:11 AM
なるほど
Avatar
そうか、本質的にasync awaitは待ち受けでしかなくて割り込みの概念はないんですね
8:16 AM
それだとコールバックパターンの完全な置き換えには成り得ないな
Avatar
omochimetaru 9/24/2021 8:17 AM
割り込みの概念?
Avatar
var done = (() -> Void)? func a() async { await withUnsafeContinuation { continuation in done = continuation.resume } // A } func b() { done?.() // B done = nil } こういうコードがあったときに、同一Actor上で await a(), b()の順番で呼び出した時に //B -> //A の順番で実行されるってことですね
8:20 AM
//A -> //B になっていてほしい。もしa()の処理の先にもう一個awaitがあったら、はじめてそこで//Bに帰ってくる、みたいな
8:20 AM
この辺が他の言語のyieldとかなり違うし、UI、特にアニメーションで使えないねとなる原因でもある (edited)
Avatar
Avatar
omochimetaru
Actor ContextをまたぐときはSendable closureしか渡せない、というのが良いのでは
Actor ContextをまたぐときはSendable closureしか渡せない、というのが良いのでは
Swift5.6だと警告が出るので、Swift6ではエラーになりそうですね。 Cannot pass argument of non-sendable type '(() -> Void)?' across actors
Avatar
Avatar
tarunon
var done = (() -> Void)? func a() async { await withUnsafeContinuation { continuation in done = continuation.resume } // A } func b() { done?.() // B done = nil } こういうコードがあったときに、同一Actor上で await a(), b()の順番で呼び出した時に //B -> //A の順番で実行されるってことですね
omochimetaru 9/24/2021 8:29 AM
await a() b() ↑こうかいたら、 // A が終わるまで、 await a() が返ってこないので、 // A -> B の順番にならんか?
Avatar
デッドロックになりそう
Avatar
omochimetaru 9/24/2021 8:29 AM
あ、done が共有されてるのか、そこを読めてなかった、もう一度考える (edited)
Avatar
多分、yieldはyieldで別の言語機能として出てくるから、async awaitはこれで良くって
8:30 AM
今使おうとしたのは用途外ってことだろうね
Avatar
omochimetaru 9/24/2021 8:31 AM
いや、やっぱり同じじゃないのか? // A に到達しないんじゃない?
Avatar
Task.init { await a() } b() 正確にはこう
Avatar
omochimetaru 9/24/2021 8:32 AM
あ、なるほど。
8:33 AM
bの中のdoneの呼び出しの瞬間、同期的に全てが連鎖してaが完了することを期待していたけど
8:33 AM
aの中のawaitが戻ってくる前に、bが進行するってことね
Avatar
そうそう
8:33 AM
特にUIの微細な調整はそれだと困るんだよね
Avatar
omochimetaru 9/24/2021 8:33 AM
それは、aを Task.init で退避したからじゃないか?
Avatar
だからこの実装パターン自体が間違っていて
8:34 AM
yieldの言語仕様の出現を待つしかないって話
Avatar
omochimetaru 9/24/2021 8:34 AM
aの中のawaitのところで、いまのTaskに戻ってくるhopが刺さってるよね
Avatar
継続を同期で作れば解決しないですか? (edited)
Avatar
Avatar
tarunon
だからこの実装パターン自体が間違っていて
omochimetaru 9/24/2021 8:35 AM
なるほど。主張の中身はわかった。
8:35 AM
なんかうまいこと書けばやりたいことを正しく記述できる気もする。。
Avatar
同期にしたら全部解決するよ。これVoidだからだけど、値渡しとかもあるときに、もうちょっと現代的に書きたいな、async awaitは使えんやろか、使えんか。って感じ (edited)
Avatar
ふむ
Avatar
Avatar
shiz
Actor ContextをまたぐときはSendable closureしか渡せない、というのが良いのでは
Swift5.6だと警告が出るので、Swift6ではエラーになりそうですね。 Cannot pass argument of non-sendable type '(() -> Void)?' across actors
omochimetaru 9/24/2021 8:35 AM
おおそうなのか。やっぱりそういう考え方であってそうですね。
8:36 AM
まだ「割り込み」の気持ちがわからないな。
8:36 AM
aとbのどっちがどっちに割り込んでるの?
Avatar
割り込んで欲しいのは//Aがbの実行に割り込んで欲しいって感じかな
8:37 AM
async awaitはそういうのはない
Avatar
omochimetaru 9/24/2021 8:37 AM
doneはそのためのカスタムポイントって感じ?
Avatar
yieldとして使おうとしたってことですね
Avatar
omochimetaru 9/24/2021 8:38 AM
あーわかった
8:38 AM
doneが呼ばれたときに、aが走るように、ストッパーみたいにしたかったのか
8:40 AM
ああそれでyieldという話が出てくるのか
8:42 AM
同期的な「次の suspension pointまで実行を再開」する機能をSwift asyncで実装できるか、という問いなんだ
8:44 AM
無理そうな気がする。 Generatorをawaitを使って書けるラッパーを実装できないか考えてみたけど、 yield側とdrain側の両方でどこかしらawaitを書くことになっちゃってどうしても待ちが出そうだ。 (edited)
Avatar
async awaitはまあいいけど、AsyncStreamのcontinuationの受け取りがyieldなのは、オマエ〜〜〜って感じになった
Avatar
ああ、continuation.yieldはそのまま先に進むからか
Avatar
進まないンゴ
8:50 AM
yield(嘘)
8:50 AM
ああ、進むのは、AsyncStreamのcontinuation.yieldの先の行にさっさと進んじゃいますね
Avatar
JSとかのは呼び出し側が.next()相当のやつを呼ばないとyieldの先に進まなかったよなと
Avatar
そうそう
Avatar
そういう協調して動くカスタムExecutorを作ればいけそう
8:53 AM
いけるかな
Avatar
omochimetaru 9/24/2021 8:53 AM
AsyncStream.Continuation のメソッド名は yield だから、generator的なものかと思ってしまうということか。
Avatar
完全に期待しちゃったよね
Avatar
カスタムExecutorって部分的に指定するとかってできるんでしょうか?
Avatar
アクターにExecutorを指定できるんですよ
Avatar
omochimetaru 9/24/2021 8:56 AM
actor Generator { ... }
8:56 AM
こんな感じにできるかもしれないってことか
Avatar
そうそう
Avatar
激アツそう
Avatar
ただconsumer側もproducerと同じactorにジョブを投入する必要があるので、記法が微妙になるかも (edited)
Avatar
おお。actorの宣言時にExecutorを指定するための何らかのシンタックスがある?
Avatar
何だったかな、computed propertyが指定できるんですよね
Avatar
結局MainActorで実行ができないから、UIに当てれないみたいな結果になりそうw
Avatar
omochimetaru 9/24/2021 8:58 AM
var serialExecutor だっけ (edited)
8:59 AM
これだこれ
Avatar
Avatar
tarunon
結局MainActorで実行ができないから、UIに当てれないみたいな結果になりそうw
これになりそう…
Avatar
omochimetaru 9/24/2021 9:00 AM
MainActor は特別なものじゃなくて @globalActor がついただけの型名なのか。
Avatar
Avatar
Yuta Saito
これになりそう…
omochimetaru 9/24/2021 9:00 AM
あ〜なるほどね
Avatar
Avatar
omochimetaru
MainActor は特別なものじゃなくて @globalActor がついただけの型名なのか。
Android で GL スレッド必須とかあったけど、ああいうので @MainActor みたいな @GLActor 的な @globalActor も作れるんじゃないかと思ってる。 (edited)
Avatar
お〜 Actor プロトコルがそもそもあってそれを使うのか
9:01 AM
すべてのactorは暗黙的に Actor にconformしてると
Avatar
Avatar
koher
Android で GL スレッド必須とかあったけど、ああいうので @MainActor みたいな @GLActor 的な @globalActor も作れるんじゃないかと思ってる。 (edited)
omochimetaru 9/24/2021 9:02 AM
GLスレッドはGLSurfaceViewごとにあるからglobal singletonにはならなそう。
Avatar
あれ?そうだったか。じゃあただの actor だ。
Avatar
omochimetaru 9/24/2021 9:02 AM
GLSurfaceViewごとにGLContextとスレッドが作られる。
9:03 AM
global actorって、ようするに、
9:03 AM
見えない引数としてただのactorが来てるのと同じ事になるんだろうか?
9:04 AM
ただのactorだとインスタンス同一性が動的になるから、 静的に解析できるglobal actorじゃないとできないこともあるのかな?
Avatar
型やインスタンスを越えて actor-isolated な API を散らばらせられますよってだけじゃないのかな?
Avatar
omochimetaru 9/24/2021 9:05 AM
ああそうか、ただのactorの場合は散らばらせることはできないか
9:05 AM
isolatedなコードを書きたければ、actorにたいするextensionとして書く必要があるから
9:05 AM
全部そのactorのメソッドの形で集約してしまう?
Avatar
だし、同じ型の actor でも異なるインスタンスだと別 actor になっちゃうし。
Avatar
omochimetaru 9/24/2021 9:06 AM
extension にしないで引数で受け取る方法があった気がするんですよ
Avatar
MainActor.run ?
Avatar
omochimetaru 9/24/2021 9:07 AM
runじゃなくて
9:07 AM
関数の引数にActorを受け取りつつ
9:07 AM
この関数の本文はこの引数のActorの中だとしますよって記法
Avatar
isolated ですか?
Avatar
Avatar
shiz
isolated ですか?
omochimetaru 9/24/2021 9:08 AM
それだ! func deposit(amount: Double, to account: isolated BankAccount) { assert(amount >= 0) account.balance = account.balance + amount }
Avatar
お~
Avatar
おお
Avatar
omochimetaru 9/24/2021 9:09 AM
思い出してきたぞ。
Avatar
これで同期的操作ができるのでは
Avatar
omochimetaru 9/24/2021 9:09 AM
いや、shizさんに思い出させてもらったんですけど
9:09 AM
なので知りたいのは
9:09 AM
globalactorはようするに、これを省略してるだけと本質的に同じか?ってこと。
Avatar
sharedな気持ち以外は同じっぽい
Avatar
omochimetaru 9/24/2021 9:11 AM
それなら、 func foo(param: Int, gl: isolated GLActor) みたいな感じができるのかも。
Avatar
いけそう
9:14 AM
GLActorインスタンス側からactor contextをもらえない場合にrun的な逃げ道は必要そうだけど
Avatar
Avatar
Yuta Saito
GLActorインスタンス側からactor contextをもらえない場合にrun的な逃げ道は必要そうだけど
omochimetaru 9/24/2021 9:15 AM
MainActor.run の意味もよくわかってないんだけど、
9:15 AM
これはどうして全てのactorに生えてなくて、MainActorの実装なの? (edited)
Avatar
なんでだろう
Avatar
omochimetaru 9/24/2021 9:17 AM
ActorからUnownedSerialExecutorが取れて、そこからenqueueが呼び出せるから
9:17 AM
なんかどのActorでもできそうな気もする
Avatar
特別なことをしてるわけじゃないから任意のactorで出来るはず
9:17 AM
あ、
9:18 AM
任意のactorではなくglobal actorが正確だ いやそんなことないな。actorで出来るな (edited)
Avatar
omochimetaru 9/24/2021 9:18 AM
enqueueできるのはjobだからクロージャは入れられないか。
9:20 AM
/// A service which can execute jobs. @available(SwiftStdlib 5.5, *) public protocol SerialExecutor: Executor { // This requirement is repeated here as a non-override so that we // get a redundant witness-table entry for it. This allows us to // avoid drilling down to the base conformance just for the basic // work-scheduling operation. @_nonoverride func enqueue(_ job: UnownedJob) /// Convert this executor value to the optimized form of borrowed /// executor references. func asUnownedSerialExecutor() -> UnownedSerialExecutor }
9:20 AM
nonoverride ってなんやねん
Avatar
Avatar
omochimetaru
bodyに@MainActor がついてるから?
そうですね
Avatar
Avatar
Yuta Saito
そうですね
omochimetaru 9/24/2021 9:22 AM
Actorのメソッドの引数のクロージャに「 @SelfActor 」みたいな指定を付ける方法がない?
Avatar
そうそう
9:23 AM
文法の問題
Avatar
omochimetaru 9/24/2021 9:23 AM
マジか。
Avatar
selfのactorにhopするのは普通に出来るので
9:24 AM
あー、でもインスタンスの同一性を気にした静的なactor-isolation検証がムリ?
Avatar
omochimetaru 9/24/2021 9:26 AM
そうか、仮に isolatedWithSelf が指定できたとして、
9:28 AM
actor FooActor { func hoge() func run(body: isolated(self) () async -> Void) } func body(actor: FooActor) { // このactorと actor.run { // このactorの同一性が静的に必要? // actor に isolatedなので↓にawaitは要らない actor.hoge() } } (edited)
Avatar
そうそう
Avatar
Avatar
Yuta Saito
そうそう
omochimetaru 9/24/2021 9:29 AM
うーんでもこのくらいシンプルなケースならキャプチャしてる同じ変数だからOKぐらいの検証はできそうよ (edited)
Avatar
頑張ればできるか…
9:31 AM
actorのメソッドとして書けばselfが不変というのは強力な前提なんだな
Avatar
omochimetaru 9/24/2021 9:32 AM
self 不変なるほど。
9:32 AM
run がないのが、いまは↑で書いたような実装とか文法仕様がないから作れないよってだけなのか、 それとも本質的に、一般にrunを提供するとactorシステム上の意味論上の安全性の問題などがあるのか、気になります。 (edited)
Avatar
waiwaiの途中だけど・・・ さっきの Publisher の購読、 extension なしだとこれでいける気がする。 override func viewDidLoad() { super.viewDidLoad() let task = Task { [weak self] in guard let state = self?.state else { return } for await _ in state.objectWillChange.values { guard let self = self else { return } // state を View に反映する処理 self.nameLabel.text = state.user?.name } } cancellables.insert(.init { task.cancel() }) } (edited)
Avatar
これは。。。。
Avatar
for await _ in ここで受け取った値を使わないと壊れるのでは?と思ったのと
12:49 PM
cancellables.insert(.init { task.cancel() }) このためにCombineをimportするのはやっぱりなんか違う気がするな〜
Avatar
@hironyticextension よりはちょい面倒ですが、 extension なしならギリ許せるレベルかとおもいますがいかがでしょう?
Avatar
stateがObservableObjectなのかな
Avatar
Avatar
tarunon
stateがObservableObjectなのかな
あ、そうです。 stateObservableObject で、 objectWillChange を購読してます。結局元々 import Combine してるのでいいかなと。
💡 1
Avatar
extensionなしだと、そうなりますね!
12:53 PM
2つ以上購読するとき、task 変数の名前を考えるお仕事がでてきますね
😭 1
Avatar
Avatar
hironytic
2つ以上購読するとき、task 変数の名前を考えるお仕事がでてきますね
こういうのは var task にして逃げることあります。
Avatar
まあそれはあり
12:55 PM
Kotlinのスコープ関数的なものがあればいいのにな
Avatar
スコープ関数自作して使ってます
12:57 PM
これを使う場合だと extension Task: Scopeable {} Task { ... }.let { (x) in cancellables.insert(.init { x.cancel() }) } (edited)
Avatar
それだと名前を考えなくて済む(ただそれだけですがw)
Avatar
僕は do でスコープ切りますね。
Avatar
extension がちょっとでも出るなら Task { ... }.dispose(to: &bag) にしちゃうし、実際その方が楽。
Avatar
ようやく一日以上考えて ObservableObjectobjectWillChange を subscribe する答えが得られた・・・。 Swift Concurrency むずい。
12:59 PM
チートシート直さないと・・・。
Avatar
willChangeのはSwiftUI最初期のころにこれdidChangeだと壊れるくね?みたいな話があった気がする
Avatar
Avatar
tarunon
extension がちょっとでも出るなら Task { ... }.dispose(to: &bag) にしちゃうし、実際その方が楽。
omochimetaru 9/24/2021 1:00 PM
.let 生やすぐらいなら専用の dispose(to:) つくったらいいね。
Avatar
Publisher に限ればどうせ Combine だし、ひろんさんの extension が一番手軽そう。
Avatar
もはや毎回.dispose(to: ) 書くのも怠いな
Avatar
問題は .store(in:) を書くのを忘れても警告が出るわけでもなんでもないことですね
Avatar
Avatar
tarunon
もはや毎回.dispose(to: ) 書くのも怠いな
omochimetaru 9/24/2021 1:02 PM
僕はViewControllerに対して addAction みたいなメソッドはやしてて、この話題で言うところのTaskとcancellablesへの登録をいっぺんにやってますね。
1:02 PM
それはRxSwiftで組んでるけど、Swift Concurrencyになっても同じようにすると思う。
Avatar
Avatar
hironytic
問題は .store(in:) を書くのを忘れても警告が出るわけでもなんでもないことですね
あー、 Task.init@discardableResult だからか。そこが sink と違うのか。 (edited)
1:04 PM
そうだ、昼書こうと思って書き忘れたんだけど、 AsyncSequence を考えると Task.init の implicit self capture はよくなかったのでは?
Avatar
Task<T, E>から.cancelを取り出すresultBuilder使ったら、
Avatar
AnyCancellable を返す Task のようなものがあれば
Avatar
self.bag = bag { Task { ... } Task { ... } Task { ... } } みたいに出来る気がする
1:05 PM
結局AsyncSequenceが出てきたら、implicit self captureだろうがなんだろうが
1:06 PM
問答無用でタスクが破壊される vs うっかりメモリリークする の構図でしかなくて、
1:06 PM
Taskをキャプチャしたら結局メモリリークするのには変わらない、ということになったと思います。今のCombineと同じで。
Avatar
Avatar
tarunon
結局AsyncSequenceが出てきたら、implicit self captureだろうがなんだろうが
implicit self captureだとself.も[self]も書かなくてもアクセスできるので、うっかりが起こりやすくないですか?
Avatar
うーん、AsyncSequenceに終端があれば問題ないはずなんですよね
1:19 PM
なんというかそれってfor文使うと無限ループして危ない!と言っているのと変わらない気がしていて
1:19 PM
いくつかの用途では終端=selfのdeallocになりがちなので、って話だからなんですけど
1:19 PM
それはもうちょっと他の落とし所があるんじゃないかなと思います
1:21 PM
こんぐらい宣言すればめちゃ快適になれそう
1:21 PM
TaskBagはdeinitでキャンセルしてるだけのclassでし
Avatar
Avatar
hironytic
AnyCancellable を返す Task のようなものがあれば
extension Task: Cancellable {} Extensionは↑これだけにして AnyCancellable(Task { ... }).store(in: &cancellables) とすれば、 .store(in:) 忘れたら怒ってくれます。 AnyCancellable から忘れたらどうしようもないけど (edited)
Avatar
なお無理にResultBuilder使わなくてもTaskBagに可変調引数のinitを生やしたらそれでいいっちゃいい
Avatar
@koher ↑↑どうでしょう 🙂
Avatar
Avatar
hironytic
extension Task: Cancellable {} Extensionは↑これだけにして AnyCancellable(Task { ... }).store(in: &cancellables) とすれば、 .store(in:) 忘れたら怒ってくれます。 AnyCancellable から忘れたらどうしようもないけど (edited)
omochimetaru 9/24/2021 1:27 PM
そのconform面白いですね。cancelメソッドが生えてるんだし実際ただしい。
Avatar
むしろ Cancellable は Foundation にあってほしいw
Avatar
omochimetaru 9/24/2021 1:29 PM
Conccurency.Task.CancellationError があるのだから、 Conccurency.Cancellable があって良さそう。
1:29 PM
いや、Concurrencyだと、CancellableなものがTaskしかないから、要らないのか。
Avatar
うーーん、やっぱり複数の場合はTaskGroupを使うでいいのではないでしょうか?
1:35 PM
ViewControllerのdeinit自体を一つのTaskのcancelと見做して、それに連なるTaskのインスタンスを全てChildTaskであるとすれば、ごく自然な実装になる
Avatar
omochimetaru 9/24/2021 1:43 PM
たしかに、同じ箇所で起動する購読Taskは、一つのTaskGroupにまとめられるはずかも。同じ箇所で起動したなら解放タイミングが同じはずだから。
Avatar
Avatar
hironytic
@koher ↑↑どうでしょう 🙂
store(in:)はCancellableであれば使えるから https://developer.apple.com/documentation/combine/cancellable/store(in:)-95sfl AnyCancellableで囲む必要はない?
Avatar
お、そうなんですね!
1:46 PM
いやしかしAnyCancellableで囲まないと、 .store(in:) なしでは怒ってくれない 😩
Avatar
omochimetaru 9/24/2021 1:46 PM
Task.init が discardable なのってなんでなんでしょう。
Avatar
Avatar
hironytic
いやしかしAnyCancellableで囲まないと、 .store(in:) なしでは怒ってくれない 😩
でも結局囲み忘れたら怒ってくれないのでは😂
Avatar
omochimetaru 9/24/2021 1:46 PM
原則として、そのうち停止するはずだから?
Avatar
キャンセルしない場合は多いから?投げっぱなしでいいやつ
Avatar
Avatar
omochimetaru
Task.init が discardable なのってなんでなんでしょう。
戻り値使わないこともおおいので。
Avatar
Avatar
koher
でも結局囲み忘れたら怒ってくれないのでは😂
その通りですw
Avatar
@IBAction で非同期発火とか。
Avatar
omochimetaru 9/24/2021 1:48 PM
うーん。投げっぱなしで良いことはほぼなくて、副作用が起きる前にコンテキスト的なものの終了に合わせてキャンセルする必要があるのは、非同期の原則だと思うんですよねえ。
1:49 PM
副作用が起きるところで、「終了してたら何もしない」って制御を入れる方式だと、そのタイミングまで無駄に計算リソースを使ってしまう事になるし。まあ負荷的な実害はほぼないけど。 (edited)
Avatar
Avatar
omochimetaru
副作用が起きるところで、「終了してたら何もしない」って制御を入れる方式だと、そのタイミングまで無駄に計算リソースを使ってしまう事になるし。まあ負荷的な実害はほぼないけど。 (edited)
UIViewのアニメーションとかわざわざ停止しなくない?
Avatar
omochimetaru 9/24/2021 1:50 PM
というか、終了してたら何もしないという分岐をするぐらいなら、終了するときに止めればいいじゃん、という。
Avatar
Avatar
koher
UIViewのアニメーションとかわざわざ停止しなくない?
omochimetaru 9/24/2021 1:51 PM
あれは特殊で、アニメーションが終わる前から、見かけの値はコミットされるので、
Avatar
投げっぱなしは無いにしても、Storeしないと勝手にキャンセルされる、は論外で
Avatar
omochimetaru 9/24/2021 1:51 PM
表示がディレイしてるだけで見かけ上は同期な感じなんですよね。
Avatar
何もしない分岐って大抵 guard let self = self else { return } で実現されてるから余分にすることあまりないのでは?
Avatar
omochimetaru 9/24/2021 1:51 PM
まあ、アニメーションの終わりをつなげたいときは、話が違うんですけど。
Avatar
TaskがdiscardableResultなのが行き過ぎなのかもしれないって話ではありそう
Avatar
Avatar
koher
何もしない分岐って大抵 guard let self = self else { return } で実現されてるから余分にすることあまりないのでは?
omochimetaru 9/24/2021 1:52 PM
その分岐を実行するコストに違和感を持ってますね。
Avatar
確かに投げっぱなしたいときは _ = Task { } にしてる方がむしろわかりやすいかもしれない
Avatar
omochimetaru 9/24/2021 1:53 PM
「終了してたら何もしない」よりは、「終了するときに止める」のほうが、シンプルに、あるべき状態だと思うって話です。
1:53 PM
「終了してるけど何もしない残像がちょっと遅れて残る」のは、状態管理的にも気持ち悪いです。
Avatar
Avatar
omochimetaru
「終了してたら何もしない」よりは、「終了するときに止める」のほうが、シンプルに、あるべき状態だと思うって話です。
そこに実際問題になるほどのオーバーヘッドが存在しないなら、コードをシンプルに保ちたい。ダウンロードとかは止めるとして。
Avatar
omochimetaru 9/24/2021 1:54 PM
URLSessionとか昔からあるAPIは基本そういう設計になっていて、cancelメソッドとかで停止した場合、ギリギリのタイミングだったとしても、コールバックとか呼び戻されることは無いんですよね。
Avatar
まあ実際にトランザクション走るようなコードとか大量に走ってオーバーヘッドが問題になるような箇所じゃ無ければ真面目にキャンセルしないですよね
Avatar
Avatar
koher
そこに実際問題になるほどのオーバーヘッドが存在しないなら、コードをシンプルに保ちたい。ダウンロードとかは止めるとして。
omochimetaru 9/24/2021 1:55 PM
いま話してるようなcancelを呼ぶコードを最後にちょっと付け足すぐらい、十分シンプルなままだと思います。
Avatar
RxSwiftは人間が考えなくてもちゃんとキャンセルされるようにできていて、あれはあれで整っていた
Avatar
omochimetaru 9/24/2021 1:57 PM
むしろ、initしっぱなしで忘れるリスクのほうが、本当に止めたいダウンロードみたいな処理が出てきたときに、見逃すツケのほうが高くつきませんかねえ
1:58 PM
The initializers are marked with @discardableResult because the task itself will immediately execute the operation and run to completion when the handle is unused. This is a fairly common use case for fire-and-forget asynchronous operations.
Avatar
確かに Task.init が @discardableResult じゃなければ、 extension Task: Cancellable {} だけで十分なんですね。storeしないと勝手にキャンセルされるわけではないし、何もしなければ警告が出るし、 store(in:)Cancellable で利用できるなら、storeしたら、bagの削除とともにキャンセルされるようになるし。 (edited)
Avatar
Avatar
hironytic
確かに Task.init が @discardableResult じゃなければ、 extension Task: Cancellable {} だけで十分なんですね。storeしないと勝手にキャンセルされるわけではないし、何もしなければ警告が出るし、 store(in:)Cancellable で利用できるなら、storeしたら、bagの削除とともにキャンセルされるようになるし。 (edited)
omochimetaru 9/24/2021 1:59 PM
そうそう。
2:00 PM
「fire-and-forgetなユースケースはよくある(fairly common) 」だかららしい。
Avatar
それ自体は間違ってないと思う
2:01 PM
まあでもバランス考えるとたしかに
2:01 PM
discardableResultとimplicit self captureは行き過ぎのような気がしてきたな
Avatar
omochimetaru 9/24/2021 2:01 PM
and run to completion when the handle is unused
↑ここはどういう意味だろう。
Avatar
Avatar
tarunon
discardableResultとimplicit self captureは行き過ぎのような気がしてきたな
omochimetaru 9/24/2021 2:02 PM
まあ0304はレビュー終わっちゃったんで今更なんだけどね・・・
Avatar
どっちにしても、UIKitよりはSwiftUIの方を見て仕事してそうだなとは思いますね
Avatar
Avatar
omochimetaru
and run to completion when the handle is unused
↑ここはどういう意味だろう。
ストアしなくても勝手にキャンセルされるわけではない、ってことかなあ。。。 (edited)
Avatar
Avatar
hironytic
ストアしなくても勝手にキャンセルされるわけではない、ってことかなあ。。。 (edited)
omochimetaru 9/24/2021 2:03 PM
ああなるほど。もし、deinitで自動キャンセルな仕様だったら、まずいけど、そうじゃないから最後まで行くよってことか。
2:04 PM
逆説的な説明になってるな。そういう順番で考えてたのか。
Avatar
sinkの場合はcancellableをretainしておかないと解放されちゃうというのがあって、CombineだとFutureでも投げっぱなしにできなくて面倒みたいなのはあった。
Avatar
omochimetaru 9/24/2021 2:06 PM
なるほど。
2:06 PM
止まるときに止めたらいいは、僕の意見だから、まあそこは、guard returnすればいいなら楽でいいという立場から考えると
2:06 PM
それでもまだおかしいことになってると思ってて
2:06 PM
AsyncSequenceが導入されたことによって、
2:07 PM
終了しないfor - await が出てくるようになって、それをセットアップするためのTaskを作るのがセオリーになっているから、
2:07 PM
そういうTaskは、for-awaitを止めるためのcancelチェインが必要なので、
Avatar
Avatar
omochimetaru
まあ0304はレビュー終わっちゃったんで今更なんだけどね・・・
どっちもAsyncSequenceとの組み合わせがあまり考えられてなさそうな。implicit self captureはともかく、discardableResultは警告の問題だし将来変えられるかも?
Avatar
そこがもうちょっとなんとかなんねーかなっていうのは思う
Avatar
omochimetaru 9/24/2021 2:07 PM
↑のfairly commonが覆されてるのが、ねじれているところじゃないかしら。
Avatar
ループ構造とキャプチャ対象が循環しなければ
2:08 PM
別にTaskをガチャガチャやんなくていいんす
Avatar
Avatar
koher
どっちもAsyncSequenceとの組み合わせがあまり考えられてなさそうな。implicit self captureはともかく、discardableResultは警告の問題だし将来変えられるかも?
omochimetaru 9/24/2021 2:08 PM
ですね。 async sequenceに対する無限forループを構築するときの書き方だけの話なら、 それようのオペレータというか書き方が別に提供されるのでもいいのかも。
Avatar
Task { [weak self] in for await ... { /* guard let self*/ } } てか別に
Avatar
omochimetaru 9/24/2021 2:10 PM
なんかこれ以上楽にならない気もするな。
Avatar
guard let self else return いれてれば
2:10 PM
Taskはキャプチャいらんがな
2:10 PM
勝手にbreakしてTaskは終わる
Avatar
omochimetaru 9/24/2021 2:10 PM
元のstreamが別の方法でdeinit経由で終了すればいいだけか。
2:10 PM
NotificationCenterとかは駄目だよね。
Avatar
いやちゃんと終わるはず
Avatar
元のstreamが終わらないとだめ
Avatar
だめなんですかぁ
Avatar
guard let が動くのが、次の値が来たときですよね。
Avatar
Streamへの参照がなくなっても、Taskが勝手に終わらないのルールがあっちゃうからダメなのか
2:11 PM
いやぁ??
Avatar
Avatar
hironytic
guard let が動くのが、次の値が来たときですよね。
omochimetaru 9/24/2021 2:12 PM
いや、そこは、async iterator . next がnilを返して止まるんで、guardにいかずに、forが終わります (edited)
Avatar
いやそれはTaskをcancelしたら、ですよね。
Avatar
omochimetaru 9/24/2021 2:13 PM
元のstreamが解放されるときにも停止する実装だったら止まる。
Avatar
それはそう
Avatar
停止すると思いますね
Avatar
omochimetaru 9/24/2021 2:13 PM
ただ、NotificationCenterからくるasync sequenceとかだったら
Avatar
AsyncStreamのcontinuationに、onTerminationっていう開放用のハンドラがある
Avatar
omochimetaru 9/24/2021 2:13 PM
やっぱりunsubscribeをしないといけない
Avatar
しなくていいよ
2:13 PM
開放されるなら、だけど
Avatar
omochimetaru 9/24/2021 2:14 PM
NotificationCenter.mainはシングルトンだから解放されないので。
Avatar
unsubscribe(cancel)しないとonTerminationが呼ばれないんじゃないですかね。
Avatar
ちょっとためしてみよう
2:14 PM
onTerminationが呼ばれるなら、Notificationも多分管理いらないと思います
2:15 PM
なぜならNotificationCenterとAsyncSequenceのオブジェクトは別なので
2:15 PM
AsyncSequenceがonTerminateで購読破棄をして、NotificationCenterからAsyncSequenceへの参照がなければ成立しますね
Avatar
omochimetaru 9/24/2021 2:15 PM
tarunonが想定してる挙動だといったい何を起点に全体が停止するん?
Avatar
[weak self] <-このselfが消えたらguard let self = self else { break or return } でループの外に出てTask自体が完了し
Avatar
onTerminationが呼ばれるのが、for await を break で抜けたとか、AsyncSequenceのprefixで先頭から指定した数だけきたら終わるとか、そういうときじゃないと
Avatar
その結果キャプチャされていたAsyncSequenceのRefCountが0になる
Avatar
Avatar
tarunon
[weak self] <-このselfが消えたらguard let self = self else { break or return } でループの外に出てTask自体が完了し
omochimetaru 9/24/2021 2:17 PM
なるほど。そのguardはfor-awaitの本文に書いてあるguardだよね?
Avatar
そうだね、最低その処理は書かないといけないから
Avatar
その guard let self = self に流れるのが、次の値がきたときだから、次の値がこなかったら流れないように思うんですよね
Avatar
omochimetaru 9/24/2021 2:17 PM
俺の想像だと、for - await の 頭のところでawaitしてて、本文に突入してないから、値が来るまでそのguardによる脱出ができないと思うんよな。
Avatar
そっちに寄せてるんじゃないだろうかというのはSwiftConcurrencyの内容を確認した時からそう思っていることで
2:18 PM
それは問題じゃないってことなんじゃないですかね
2:18 PM
問題だとしても些細な話ということだと思う
Avatar
Avatar
omochimetaru
俺の想像だと、for - await の 頭のところでawaitしてて、本文に突入してないから、値が来るまでそのguardによる脱出ができないと思うんよな。
そうそう、ぼくも同じ意見で。NotificationCenterに登録したけど一度もNotifyされない場合とか、ずっと登録したままじゃないかと。
Avatar
投げっぱなしでええんやでっていう意見に、それが問題であったとしても些細な話っていうニュアンスが含まれていると思うんですよね
2:20 PM
discardableResultがその結果出てきたものという気がする
Avatar
omochimetaru 9/24/2021 2:20 PM
投げっぱなしの話は 「and run to completion」だからってのはわかるんだけど for-awaitだと、run to completionしないから、おかしくね、という疑問を持っているところ。
Avatar
まぁimplicit self captureは失敗だけど…
Avatar
omochimetaru 9/24/2021 2:22 PM
過去に議論されてないかなあ。
Avatar
omochimetaru 9/24/2021 2:29 PM
フォーラムで軽く検索したけど見つからず。
Avatar
ところで Task.init (旧 async )は外側のactor contextが引き継がれるのに、 TaskGroup.addTask (旧 TaskGroup.async )は引き継がれないのはなぜ
2:34 PM
複数の場合は TaskGroup を使えばうんぬんというのを試してみようと思ったんですが Task { await withTaskGroup(of: Void.self, body: { group in group.addTask { // ここが non-isolated になっちゃう } group.addTask { // ここが non-isolated になっちゃう } }) }
2:36 PM
いや、なぜかといえば、 @Sendable なクロージャーを取るからなんですが、 Task.init と同じ扱いにしてないのはなぜ、という意味で。
Avatar
extension NSObjectProtocol where Self: NSObject { func observe<T>(keyPath: KeyPath<Self, T>) -> AsyncStream<T> { AsyncStream { continuation in let observation = self.observe(keyPath, options: [.new]) { _, change in if let newValue = change.newValue { continuation.yield(newValue) } } continuation.onTermination = { @Sendable _ in print("onTermination") observation.invalidate() } } } } こういうの生やして実験してみたけど
2:44 PM
onTermination発火してましたよ
2:44 PM
で、NotificationCenterもこれと同じような実装になっていて、破棄されるんじゃないかと踏んでいます
Avatar
omochimetaru 9/24/2021 2:47 PM
おお?
Avatar
最後の1回が呼ばれないとonTermination発火しないから終わらねーじゃん、はまあそれはその通り。
2:48 PM
でも投げっぱなしでオッケー✨っていう価値観なら、無害なクロージャと化したTaskは大した問題ではないに分類されると思います。
Avatar
Avatar
tarunon
最後の1回が呼ばれないとonTermination発火しないから終わらねーじゃん、はまあそれはその通り。
omochimetaru 9/24/2021 2:50 PM
ああ、最後の一回はそうなのね。そうするとそのクロージャからキャプチャしてる参照から思わぬオブジェクトがつながっててメモリリークが問題になりそうだから、その方針は厳しいんじゃないか。 (edited)
Avatar
その場合はそもそもweak selfがnil化しないから
2:51 PM
ところで continuation.onTermination の引数は
2:51 PM
cancelled or finishedのenumで
2:52 PM
多分for文が最後まで回ったかどうか、がここに来るんだと思います
2:52 PM
breakならcancelled
Avatar
Avatar
tarunon
その場合はそもそもweak selfがnil化しないから
omochimetaru 9/24/2021 2:52 PM
たしかに多くの場合で循環が問題になるのはselfがリークしてる場合ではあるな。
Avatar
利用側はこんな感じね Task { [weak self] in guard let observeFoo = self?.observe(keyPath: \.foo) else { return } for await foo in observeFoo { guard let self = self else { return } self.printFoo(foo) } }
2:54 PM
でこれは流石にウッて感じなのはその通りなので
2:54 PM
まあやっぱりselfの何某かを購読するってのは無理があるらしい
2:55 PM
子のメンバを親が購読して子に通達する、というユースケースならはまりそうだけどね
2:56 PM
Task { [child, weak self] in for await foo in child.observe(keyPath: \.foo) { if self == nil { return } child.printFoo(foo) } } うーーん。。。 (edited)
2:57 PM
やっぱりなんか終端記号の付与の仕方がもうちょっとなんとかなってほしいな
2:58 PM
AsyncSequenceのオペレーターにそういうのが追加されるかも (edited)
Avatar
Taskをinitするときにweakifyするオブジェクトを渡してあげて、内部でそれをthrows propety(nilならerror)として参照すれば、結構上手く行くんじゃ無いか
3:23 PM
これは普通に便利かも
Avatar
class TaskContext<T: AnyObject> { private weak var weakValue: T? var value: T { get throws { guard let value = weakValue else { throw CancellationError() } return value } } init(weakValue: T?) { self.weakValue = weakValue } } extension Task where Failure == Error { @discardableResult init<T>(priority: TaskPriority? = nil, context: T, operation: @Sendable @escaping (TaskContext<T>) async throws -> Success) { let taskContext = TaskContext(weakValue: context) self.init(priority: priority, operation: { try await operation(taskContext) }) } } こういうのを作っておく するとこうなる Task(context: self) { context in for await foo in try context.value.observe(keyPath: \.foo) { try context.value.printFoo(foo) } } (edited)
3:31 PM
書き味はめちゃくちゃいいね
Avatar
omochimetaru 9/24/2021 3:33 PM
property wrapper使って.value消せるかな?
Avatar
throwsでアクセスできなくないか
3:33 PM
やってみよう
3:34 PM
Property wrappers currently cannot define an 'async' or 'throws' accessor
3:34 PM
これが解禁されたPropertyWrapperが、目玉だぜ!最高!ってWWDCに出てくる可能性はほんのちょっとだけありそうだ (edited)
Avatar
Avatar
tarunon
Property wrappers currently cannot define an 'async' or 'throws' accessor
omochimetaru 9/24/2021 3:36 PM
だめかー
Avatar
これは個人的にはかなり正解に近い拡張な気がするけど、最後の1滴が来てくれないとTaskが残ってる問題は、未解決だね。
Avatar
omochimetaru 9/24/2021 3:38 PM
IUOはTのようにアクセスできてnilだとクラッシュするけど (edited)
3:38 PM
Tのようにアクセスできてnilだと例外が飛ぶっていう仕組みは
3:38 PM
多くの状況で便利そうな気がした。
Avatar
上手いよね、ちょっと上手く行きすぎたからGistに乗せてTwitterに放流して自慢したろw
Avatar
omochimetaru 9/24/2021 3:42 PM
Avatar
おしい
Avatar
omochimetaru 9/24/2021 3:43 PM
propertyWrapperだとできないならcallAsFunctionにしたら () だけにできるw
Avatar
気持ち的にはやっぱり for の 行のtryで離脱してほしいのでAsyncZipSequenceないかと思ったけどないか
Avatar
作ればいいよ
Avatar
AsyncFlatMapSequenceがあるのでそれでいけるかも
Avatar
最初にその方法やったんだけど、思ったより長くなるし結局tryは外せなかったから
3:50 PM
今のにした
Avatar
selfを for await (self, notification) in の形式で受け取るのはちょっとだるさありますよね
Avatar
それ
3:52 PM
しかもselfの名前使うとセグフォ出しおる
Avatar
Avatar
あれ?もしかしてflatMap使えばthrowsせずにいける?
3:55 PM
って思ったけど無理やわ。
3:56 PM
flatMapで作った終端記号はflattenされるときに接続記号になっちゃう (edited)
Avatar
一晩でめちゃくちゃ流れててもう追えない
Avatar
Swift5.5へのback deployment、ひとまずmergeされましたね。(まだ諸々のbug fix必要みたいですが)
Alright, there's a bit more to come here to fix some known bugs, but this is a good baseline to land.
https://github.com/apple/swift/pull/39342
(edited)
👀 1
🎉 1
Avatar
throws/asyncをPropertyWrapperに許可する方向性とはまた別に、weakキャプチャのthrowable版を用意するという方向の進化もありそうだなと思った。そもそもOptionalをthrowableに変換するオペレーターがあれば実はそれで良いのでは?解りやすくなると思う
5:19 AM
override func viewDidLoad() { super.viewDidLoad() Task { [weak self] in for await value in try self.tryUnwrapped.mySomeAsyncSequence() { try self.tryUnwrapped.use(value) } } } うん、これでいいな。
Avatar
【悲報】 cancel されても Publishervaluesnil は流れてこない。
Avatar
Avatar
koher
【悲報】 cancel されても Publishervaluesnil は流れてこない。
omochimetaru 9/25/2021 7:22 AM
えっ、それじゃあ停止できなくない??
7:22 AM
for awaitを抜けられないですよね?
Avatar
↓みたいなコードで確認したところ、 deinitcancel は表示されたけど release は表示されず。 deinit { print("deinit") } override func viewDidLoad() { super.viewDidLoad() let task = Task { [weak self] in guard let state = self?.state else { return } for await _ in state.objectWillChange.values { guard let self = self else { print("release"); return } // state を View に反映する処理 self.nameLabel.text = self.state.user?.name } } cancellables.insert(.init { print("cancel"); task.cancel() }) }
Avatar
それはそうなるんじゃ
Avatar
あ、 nil はそうか
7:24 AM
勘違いした。
Avatar
このコードはVCのdeinit時点で購読を中断しているから、selfがnilのときにguardに突入しない
7:25 AM
deinitの行を消して試すといいと思いました
Avatar
ちゃんと流れてた。
7:25 AM
override func viewDidLoad() { super.viewDidLoad() let task = Task { [weak self] in guard let state = self?.state else { return } for await _ in state.objectWillChange.values { guard let self = self else { print("release"); return } // state を View に反映する処理 self.nameLabel.text = self.state.user?.name } print("nil") } cancellables.insert(.init { print("cancel"); task.cancel() }) }
7:25 AM
お騒がせしました。
7:26 AM
よかった。
Avatar
omochimetaru 9/25/2021 7:26 AM
なんだ。
Avatar
最初に考えてた selfnil になって脱出のイメージが強すぎて、 nil で脱出が guard let selfnil で脱出と頭の中で混ざってた。
Avatar
"Swift Concurrency チートシート"のCase 18・20のコードを大幅修正しました。修正理由&内容は https://t.co/TGpCbMtgfv を御覧ください。簡単に書くと、Publisher購読についてConcurrency下でオススメできる書き方になってなかったのでfor awaitを使う形に修正しました。 https://t.co/XgP1LqaqsH
👏 5
👍 1
Avatar
Avatar
koher
UIView.animate(withDurations: 0.5, animations: { self.label.alpha = 1.0 // MainActor でないとこれができない })
まだここまでしか読んでないけど、UView.animateは2つblockとって、最初のは@escapingじゃない(即時実行される)で、問題になるのはcompletionのほうでは?と思った
Avatar
animationsもescapingだったような
6:24 AM
別スレッドから実行できるという話があるのでescapingだと思います
Avatar
Avatar
tarunon
animationsもescapingだったような
@available(iOS 4.0, *) open class func animate(withDuration duration: TimeInterval, animations: @escaping () -> Void, completion: ((Bool) -> Void)? = nil) これはおかしいような... え... (edited)
Avatar
そもそも受け取ったクロージャを加工して実行する時点で、即時実行であったとしても@escapingの記述が往々にして必要になる気がします
Avatar
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_SWIFT_DISABLE_ASYNC API_AVAILABLE(ios(4.0)); // delay = 0.0, options = 0
Avatar
@escapingだから必ず即時実行されないとは限らないので。
Avatar
いや animations は読んだ時に即時評価されないと意味不明なことになる...
6:34 AM
[UIView beginAnimtions:...]; ... [UIView commitAnimations]; の別記法みたいなものだから。 (edited)
Avatar
@escaping が即時評価されないことと等価ではないですよ
Avatar
ええと、animationsに@escapingついてなかったと思ったんだけどついててあれって思ってる。
6:37 AM
逆にcompletionに@escapingついてなくてあれって思ってる
Avatar
completionはOptionalなので
6:38 AM
Optionalに渡される時点で自明にecapingです
6:38 AM
(escapingがつくのはこの手の実装都合とか普通にあるので、即時評価と関係あるとは限らない
6:39 AM
で、実装都合のescapingが安全なescapingで、sendable不要なんですよね
6:39 AM
スレッド跨がないから。
Avatar
ふむー。
6:40 AM
なるほど...
6:40 AM
ついてないと思ってた。
Avatar
これこそ @_implicitSelfCapture ついててほしいですね
Avatar
Avatar
omochimetaru
たしかに多くの場合で循環が問題になるのはselfがリークしてる場合ではあるな。
関係あるかわからないけれど、NotificationCenterは登録するだけでリソースを食って、それで問題になったことが何度もあって、今のweakのやつも、deinitでunregister明示的にしないとweakだから勝手に消えるから(でもそれはそのnotificationが最後にもう一回来た時なので自分が出してるやつとかだと永遠に来ないこともある)放置はダメってのがあるんだけど... (edited)
7:06 AM
(あとちょっとでログに追いつく...)
Avatar
Avatar
niw
ついてないと思ってた。
omochimetaru 9/26/2021 7:31 AM
UIView.animate ってもしかして非メインスレッドから読んだら、animationsがメインスレッドに投入されるんじゃないですかね?それなら @escaping がついてるのが正しい
Avatar
Avatar
niw
関係あるかわからないけれど、NotificationCenterは登録するだけでリソースを食って、それで問題になったことが何度もあって、今のweakのやつも、deinitでunregister明示的にしないとweakだから勝手に消えるから(でもそれはそのnotificationが最後にもう一回来た時なので自分が出してるやつとかだと永遠に来ないこともある)放置はダメってのがあるんだけど... (edited)
omochimetaru 9/26/2021 7:33 AM
なるほど。ユーザ側のメモリリーク以外にも害があるのか。まあ僕は最後にもう一回来ない場合にリークするスタイルは良くないと思ってます。
Avatar
Avatar
omochimetaru
UIView.animate ってもしかして非メインスレッドから読んだら、animationsがメインスレッドに投入されるんじゃないですかね?それなら @escaping がついてるのが正しい
なのかな... それはちょっと知らない挙動かも。UIViewのこの実装は読んだことがあって、変わってないと思うんだけどなあ...
Avatar
omochimetaru 9/26/2021 7:34 AM
簡単に書ける書き方が全く等価なら採用したいけど、動作上のデメリットが有るなら、書きやすさより望ましい挙動を優先したい。
Avatar
Avatar
niw
なのかな... それはちょっと知らない挙動かも。UIViewのこの実装は読んだことがあって、変わってないと思うんだけどなあ...
omochimetaru 9/26/2021 7:34 AM
そうなんすかね。animationsのescapingは僕も昔から謎でした。
Avatar
NotificationCenter.default.notifications(named: .init("namae"), object: nil) で帰る Notifications: AsyncSequence ってそもそもどうやってunregisterできるんだろう... (edited)
Avatar
for文から抜けたらunregisterだと思いますよ
Avatar
あ、なるほど
Avatar
omochimetaru 9/26/2021 7:36 AM
forに突入するときが内部的にはmakeAsyncIteratorでこれがsubscribe
7:37 AM
forを回すたびに await iterator.next()
Avatar
Avatar
niw
なのかな... それはちょっと知らない挙動かも。UIViewのこの実装は読んだことがあって、変わってないと思うんだけどなあ...
...そんなことはなく、普通にbackground threadから呼ばれた
Avatar
Avatar
niw
...そんなことはなく、普通にbackground threadから呼ばれた
omochimetaru 9/26/2021 7:39 AM
お。じゃあanimateはやっぱりスレッドをまたげるんだ
7:39 AM
ん、ぎゃくか?
7:39 AM
(どっちにも読み取れる
Avatar
えーっと UIView.animate(duration:animations:) を呼んだその場所から普通に呼ばれてます (edited)
7:41 AM
* frame #0: 0x0000000104483a9c Test`closure #1 in closure #1 in ViewController.viewDidLoad(self=0x0000000132f08d90) at ViewController.swift:42:17 frame #1: 0x0000000104483b80 Test`thunk for @escaping @callee_guaranteed () -> () at <compiler-generated>:0 frame #2: 0x000000018529b5b0 UIKitCore`+[UIView _setupAnimationWithDuration:delay:view:options:factory:animations:start:animationStateGenerator:completion:] + 576 (edited)
Avatar
omochimetaru 9/26/2021 7:42 AM
なるほど。じゃあnonescapeっぽいな・・・
Avatar
UIKit の挙動がいきなり変わることはないと思うんですよ
Avatar
Avatar
omochimetaru
forを回すたびに await iterator.next()
ということは一度は通知を受け取る必要があって、なんか自分が通知を投げるみたいなやつを聞いてるとかの場合、guard let self else return してても、投げる自分がきえちゃってゾンビは簡単にありえるのか...
Avatar
Avatar
niw
ということは一度は通知を受け取る必要があって、なんか自分が通知を投げるみたいなやつを聞いてるとかの場合、guard let self else return してても、投げる自分がきえちゃってゾンビは簡単にありえるのか...
omochimetaru 9/26/2021 8:14 AM
いや、AsyncSequenceのソースになってるなんらかの購読が解除されれば、
8:15 AM
next()nil を返してforがbreakします。
8:15 AM
で、Task.cancel を呼べば明示的な unsubscribe になります。
Avatar
なるほど、この場合も Task.cancel 呼べいいのか。さっきちょっと試してそこで unregister されるのかなーどうなんだろうと思った。
Avatar
Avatar
niw
なるほど、この場合も Task.cancel 呼べいいのか。さっきちょっと試してそこで unregister されるのかなーどうなんだろうと思った。
omochimetaru 9/26/2021 8:32 AM
Task.initの返り値を使わない場合には、何かイベントが来るまでループを抜けられない、って話ですね。
Avatar
animationsはリピートが、とか昔聞いた気がする。
Avatar
omochimetaru 9/26/2021 8:33 AM
リピート時にまた呼ばれる?
Avatar
えーまじか
Avatar
Avatar
omochimetaru
Task.initの返り値を使わない場合には、何かイベントが来るまでループを抜けられない、って話ですね。
そうですね。気をつけて使わないといけないなという感じ。やっぱり task が @discardableResult なのはやりすぎなのかも。
Avatar
Avatar
niw
そうですね。気をつけて使わないといけないなという感じ。やっぱり task が @discardableResult なのはやりすぎなのかも。
omochimetaru 9/26/2021 8:50 AM
プロポーザルやフォーラムを軽くみた感じTask.initの仕様を議論するときにAsyncSequenceによる無限forループのことが十分に考慮されなかった気がするんですよね。 (edited)
8:50 AM
整理して聞いてみたい。
Avatar
NotificationCenterみたいな無限AsyncSequenceのfor awaitについては、一度も発動しないとリークするというのは嫌なので、不要になった時点でTaskのcancelを呼ぶのを個人的にテンプレ(定石)にしたいと思ってます。そして、その方針でいくと @discardableResult が邪魔だと思ってます。忘れたときに警告してほしい。
wakaru_ue 1
Avatar
この間Optional -> Throwsの変換をやってて思ったんですが、weak selfの方を便利にする方針はあり得るんじゃないか?と思いました
11:45 AM
どっちの方が良いのかは正直わからんな…
Avatar
Avatar
hironytic
NotificationCenterみたいな無限AsyncSequenceのfor awaitについては、一度も発動しないとリークするというのは嫌なので、不要になった時点でTaskのcancelを呼ぶのを個人的にテンプレ(定石)にしたいと思ってます。そして、その方針でいくと @discardableResult が邪魔だと思ってます。忘れたときに警告してほしい。
implicit self capture も要らないですね・・・。
👍 1
Avatar
yutailang0119 9/27/2021 7:04 AM
Swift 5.5がリリースされた。おめでとうございます。 Swift 5.5の目玉はもちろんSwift Concurrencyだ。言語機能として並行処理がサポートされた。async/awaitの構文だけでなく、Structured Concurrencyとしての整理や、actorの導入など、野心的な取り組みと言える。 Swift Concurrency Swift Concurrencyに直接関係するSwift Evolutionの提案はこれだけある。 SE-0296 Async/await SE-0297 Concurrency Interoperability with Objectiv…
👍🏻 1
Avatar
onCancelの部分、AsyncStreamの実装見て、@unchecked SendableのクラスでWrapして自前でlockしなければいけないのかなと思っていましたが、やはりそうなのですね👀 https://github.com/apple/swift/blob/main/stdlib/public/Concurrency/AsyncStreamBuffer.swift#L56
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
これ僕もコンパイルエラーになったので無理やりクラスにラップして通すことはできたんですが、それじゃダメなので何かしらの同期機構で守らないといけないんだろうなぁと思ったまま放置してました。 -warn-concurrency だとちゃんと警告出るんですね。 使うの大変すぎると思うんですが、想定ではどうやって使うつもりなんでしょうね? Proposal のコードもエラーだし、 AsyncStream がそうなってるということはそうするしかない?
Avatar
omochimetaru 9/27/2021 8:33 AM
基本的に、そもそも従来の形の非同期APIが提供される場合、
8:33 AM
なんらかの購読かタスク抽象オブジェクトに対する cancel メソッドが呼び出せるように設計されている事が多くて
8:33 AM
かつ、そのcancelメソッドはスレッドセーフになってる事が多いので、
8:33 AM
そのオブジェクトが Sendable準拠してくれていて、普通に { task.cancel() } がconccurency safeと判定される
8:34 AM
というのが自然な展開じゃないですかね?
8:34 AM
元記事でいうと、 勢いよくURLSessionTaskもSendableにしてしまっているが、スレッドセーフなはずなので大丈夫だと思う。 ↑これと同じ発想です。
8:35 AM
もしそうじゃなかったら、そもそもそのローレベルの(Swift concurrencyにラップする対象の)cancelメソッドを呼び出すことの安全性が保証できなそう。 (edited)
Avatar
Avatar
omochimetaru
そのオブジェクトが Sendable準拠してくれていて、普通に { task.cancel() } がconccurency safeと判定される
これは理想的だと思います。今はまだ Sendable に適合してないけど、適合する想定なのかな?
8:37 AM
まあ、 URLSession に限って言えば async 対応の API が用意されたからそもそも必要ないのか?
Avatar
Avatar
koher
これは理想的だと思います。今はまだ Sendable に適合してないけど、適合する想定なのかな?
omochimetaru 9/27/2021 8:37 AM
してくれないと、ユーザーがやるのはおかしいですよね。だって、ユーザーにはほんとうの意味でそのSendableの正しさを知ることが出来ないし。
Avatar
Avatar
koher
まあ、 URLSession に限って言えば async 対応の API が用意されたからそもそも必要ないのか?
omochimetaru 9/27/2021 8:38 AM
あー、それは、そうか。
8:38 AM
でも、ラップAPIを提供するんだったら、自分でラップするだけの必要な下準備も共有してほしいけど。
Avatar
Avatar
koher
まあ、 URLSession に限って言えば async 対応の API が用意されたからそもそも必要ないのか?
iOS15以前だとURLSessionのasync APIがおそらく使えないので、その場合はやはり自前の実装が必要なのかなと思ってます。 (edited)
Avatar
Avatar
shiz
iOS15以前だとURLSessionのasync APIがおそらく使えないので、その場合はやはり自前の実装が必要なのかなと思ってます。 (edited)
omochimetaru 9/27/2021 8:40 AM
そうだった。。せっかくbackdeployがあってもoverlay APIが提供されない問題。
Avatar
こんにちは〜。いい記事ですね。FoundationのクラスとかにもじきにSendableついていったりするのだろうなとは思いました。その上でSendableなクロージャからvarのキャプチャができないのはけっこう不便ですね〜
8:43 AM
lazyに初期化されるvarに対してなんらか手当があると嬉しい
Avatar
omochimetaru 9/27/2021 8:50 AM
APIに期待されるふるまいとしては withUnsafeThrowingContinuation の呼び出しが終わってからでしか onCancel が呼ばれることはないから、withUTCのなかで何かオブジェクトを作って、onCancelでそれに対してインタラクトするって前後順は大抵パターンになりそうだけど、 2つのクロージャで同じものを触ろうとしたらvarを経由する必要があって、そのvar変数自体がconcurrency safeにならないのか・・・
8:50 AM
withUnsafeThrowingContinuation がopaqueな <Handle> を返せるようになってて、 onCancel<Handle> が渡ってくる、みたいなインターフェースになっていたら、大抵の場合では使いやすそう。
Avatar
propdrtyWrapperなConcurrencySafe<T>が純正でそのうち出てくるんじゃないかな (edited)
Avatar
Avatar
tarunon
propdrtyWrapperなConcurrencySafe<T>が純正でそのうち出てくるんじゃないかな (edited)
omochimetaru 9/27/2021 8:52 AM
出たとして、それを正しく使うのが難しくない?悪用されて破滅するかも
8:52 AM
悪用するのが悪いからまあそれはいいのかな
Avatar
少なくとも現状のCancel部分はそれがないととてもとても
Avatar
Future workに出ているUnsafeTransfer みたいな感じですかね? これはUnsafeですが... // The caller *promises* that it won't use the transferred object. https://github.com/apple/swift-evolution/blob/main/proposals/0302-concurrent-value-and-concurrent-closures.md#adaptor-types-for-legacy-codebases (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0302-concurrent-value-and-concurrent-closures.md at main · apple/swift-evolution
Avatar
それっぽい
8:54 AM
当にこれじゃん
Avatar
omochimetaru 9/27/2021 8:55 AM
var に対する get/set だけ atomicにすればいいのであれば
8:55 AM
public struct AtomicOptionalReferenceStorage<Instance: AnyObject> https://github.com/apple/swift-atomics/blob/main/Sources/Atomics/AtomicStrongReference.swift#L444
8:56 AM
こういうのがあるみたいだけど、 コレ自体がstruct だから駄目なんかな?
8:56 AM
この AtomicOptionalReferenceStorage が c.c. で extension Sendable where Instance: SEndable  ならOK?
8:59 AM
いや、駄目か・・・? var それ自体の更新が保護されるわけじゃないから?
Avatar
classとstructとで動き変えたくなるヤツだなぁ
Avatar
omochimetaru 9/27/2021 9:01 AM
記事にあるように ManagedAtomicLazyReference がピッタリ正解なのか、これはやろうとしてることに対して過剰なのか、よくわからない
9:02 AM
/// A reference type holding a lazily initializable atomic /// strong reference, with automatic memory management. /// /// These values can be set (initialized) exactly once, but read many /// times. @_fixed_layout public class ManagedAtomicLazyReference<Instance: AnyObject> {
9:08 AM
一回だけセットして、後でそれを参照する、だから、ピッタリな気もする。
Avatar
いずれにしてもAnyObject縛りがアレですね
9:08 AM
結局classで囲まないといけない
Avatar
ManagedAtomicLazyReference の方がいろいろあってちょっとだけコストが低いような
Avatar
Avatar
tarunon
結局classで囲まないといけない
omochimetaru 9/27/2021 9:09 AM
こういうハンドラはそもそもclassじゃない?structだと、同じ対象に対するcancelでも変な感じ。
Avatar
omochimetaru 9/27/2021 9:22 AM
@Iceman が言ってたんだけど、 React.useEffectとかRxSwift.Observable.createは、
9:22 AM
subscribeクロージャの中でcancellerクロージャを作ってreturnさせるインターフェースになってるから
Avatar
そ結構ズルしてるstructがあるからなぁ、まあその辺は使わないやろか
Avatar
omochimetaru 9/27/2021 9:22 AM
クロージャの入れ子関係が処理の前後順保証に対応していて、varを経由する必要がないので、よく出来てますね。
Avatar
AsyncStreamはそんな感じなんだよね
Avatar
omochimetaru 9/27/2021 9:23 AM
onCancelはなんで引数で横並びにしたんだ。
Avatar
でもキャンセルは@Sendableだけど
Avatar
Avatar
tarunon
AsyncStreamはそんな感じなんだよね
omochimetaru 9/27/2021 9:23 AM
えっ、そうなんだ。
Avatar
AsyncStreamはそういえばそうだった
9:23 AM
onTermination というプロパティに任意のキャンセル処理をさす形です
Avatar
omochimetaru 9/27/2021 9:24 AM
それがcontinuationのプロパティだからクロージャの内側で登録する形なのか。
🛷 1
Avatar
ただこれはやらなくても良いになっちゃってるんだよね
Avatar
omochimetaru 9/27/2021 9:25 AM
(ソリ・・・か・・・?
Avatar
キャンセル処理を書くことを強要する意味だとRxSwiftが一番優れてる
Avatar
(「それ」→「そり」)
😆 2
t_wakaru 1
Avatar
Reactは書かなくても良い、だからビミョ (edited)
Avatar
Avatar
tarunon
キャンセル処理を書くことを強要する意味だとRxSwiftが一番優れてる
omochimetaru 9/27/2021 9:27 AM
なるほど。
9:28 AM
キャンセルしようがないときに空のDisposable書かないといけないけど、それによって反省を促されるしね。
Avatar
1. 弱参照をAsyncThrowsSequence として返し、開放時にErrorを発生させるものを作る 2. CombineThrowsSequenceを定義する の二つを作ると、キャンセラ登録無しでもちゃんと消えてくれるfor awaitが作れるけど、キャンセラ書くのとどっちが良いかと言われるとウーンって感じ
1:47 PM
Task{ [xxx self] in for try await (self, foo) in combine(self, NotificationCenter.default.observe(...)) { ... } } こんなイメージ
1:48 PM
弱参照をAsyncThrowsSequence として返し、開放時にErrorを発生させるものを作る
これ自分で作れっかな。nillingの通知って出来ましたっけ。黒魔術必要だな…
1:49 PM
.rx.deallocatedと同じ作りになる
1:51 PM
Swiftのそもそもの方向性として、キャンセラを書くことを強制するよりは、書かなくてもちゃんと動く世界を構築する、の方がやっぱり近い気がして、そう言った道具が出てくるんじゃないかな〜と思うんですよねやっぱし
t_naruhodo 1
Avatar
omochimetaru 9/28/2021 4:00 PM
任意のオブジェクトに対して実現することはできないとしても、 (edited)
4:00 PM
deinitを通知する仕組みにprotocolとして名前をつけて
4:00 PM
Task { [xxx self] って書いてるところを
4:01 PM
Task(deinitNotifiable: self) { (self) in
4:01 PM
みたいな形で書くとかできても良さそう
4:01 PM
キャンセルも動作に対する副作用ではあるので、
4:02 PM
完全に暗黙に参照解放と連動してキャンセルが発動するのはそれはそれで常に正しいとは限らないと思っていて、
4:02 PM
参照解放とタスクの停止を紐付ける宣言は何か書く形のほうが良いと思う
Avatar
omochimetaru 9/28/2021 6:10 PM
たるのんの書いてるイメージの combine(self, ...) がそれを意味してるのかな。
Avatar
そうだね
7:37 PM
この場合selfはAsyncThrowsSequenceになっていて、一回目はweak selfが取り出せて、解放されたときにerrorが吐き出される。そうすると、combineで組み合わせると解放によるエラーもしくはもう片方のasync sequenceの終端での脱出、ということになる。 (edited)
7:37 PM
エラーは別に終了でも良いけど
Avatar
hi all, I’ve discovered several stack corruption bugs related to async/await which can be reproduced in simple test programs compiled with recent nightly toolchains. i have confirmed that two three four of these bugs are present in the 5.5-RELEASE toolchain. stack corruption when using values returned by async closures the return values of ...
Avatar
もうすぐ修正(回避)されるみたいですね https://github.com/apple/llvm-project/pull/3314 The actual bug appears to have been introduced in July 2020 15 in LLVM's coroutine handling, so it's gone undiagnosed for more than a year despite LLVM coroutines being in use for a number of different features (e.g., C++20 coroutines in Clang, async functions in Swift). https://forums.swift.org/t/swift-5-5-has-serious-stack-corruption-bugs/52344/27 (edited)
Avatar
おー、、1年以上も…
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0293-extend-property-wrappers-to-function-and-closure-parameters.md at main ·...
7:00 AM
let a: (Binder<Int>) -> () = { $arg in ... } こんな風に$prefixつけて引数を宣言するとinit(projectedValue:) に渡して使えるというもの
7:01 AM
なんだけど、throwsやasyncと併用しようとすると壊れてしまう。 久しぶりに報告した https://bugs.swift.org/browse/SR-15274
Avatar
https://swift.org/blog/swift-docc/ DocC オープンソースになりました
At WWDC21, Apple announced Swift-DocC, a new documentation compiler for Swift frameworks and packages. Swift-DocC provides an effortless way to author great documentation alongside your code, and generate comprehensive documentation websites for Swift codebases. It supports API docs authored as code comments, long-form conceptual articles writte...
👏🏻 12
🎉 6
Avatar
自前クラスだとprotocolのglobalActorが検証されるけど、UIViewControllerとかは検証されないのどこが違うんでしょうかね? (edited)
Avatar
NS_SWIFT_UI_ACTORは @MainActor(unsafe) ですね
1:34 AM
@MainActor(unsafe) class Base { } protocol MyBaseProtocol: Base { func f() } class MyClass: Base, MyBaseProtocol { func f() { } }
t_thanks 1
1:34 AM
これなら通る
Avatar
へぇ〜
Avatar
おお、なるほど
Avatar
こっちの方が正しい気がしてきた @Iceman @omochimetaru @MainActor class Base { } @MainActor protocol MyBaseProtocol: Base { func f() } class MyClass: Base, MyBaseProtocol { func f() { } }
8:02 AM
unsafeの例だとexistential経由の呼び出しが、Actor保護されないという問題が出てくるはず。
8:02 AM
それを避けるためには、protocolに明示的にMainActorの宣言をしておくと良い
Avatar
MyBaseProtocolはBaseを継承する時点で MainActor にならないの?
Avatar
べきかどうかはさておき、ならないからこうなってるという理解です
Avatar
BaseのglobalActorみて何かしらエラーをだすのに、mainActorかどうかは見ていない感じになってるんでしょうかね?
Avatar
protocol周りの実装が追い付いてない説は普通にありそう
Avatar
BaseについてるglobalActorの存在を認識しているからエラーは出せるけど、それがMainActorだとわかっていないからMainActor同士のconformでもエラーが出てしまうという
Avatar
「Base部分はMainActorで保護されているのにDerived部分はそうではない」に意味があるかどうかだな
8:06 AM
型理論的にはサブタイプ側でゆるくなる分にはおかしくはないか・・・?
Avatar
BaseはMainActorだけどMyBaseProtocolは解らない、になってるわけです。足りない分の宣言を足してあげると解決する。
8:06 AM
おかしいとは思う
Avatar
基本的なポリシーとしてSwift5.5では明示的にConcurrency機能を使わない限り検査対象にならないので
naruhodo 1
Avatar
self保護を考えてるからおかしいよねえ
Avatar
全部検査するよモードにするオプションがあるので、それを付けると実装漏れかどうか分かりそう
👀 1
8:08 AM
フラグ名は忘れた…
Avatar
なるほど。緩めモードの振る舞いかもしれないか。
Avatar
-warn-concurrencyだ
Avatar
-warn-concurrency はもうつけてました😝
8:09 AM
とくに何も出ず・・
Avatar
なるほど〜
Avatar
上記に関連して疑問があるのですが、 UIViewControllerのサブクラスに@MainActorを付けるとTaskのイニシャライザのクロージャ内のwarningが消えるのは、なぜなのでしょうか? // Xcode13.1 // -Xfrontend -warn-concurrency を設定した状態で @MainActor protocol MyViewProtocol: UIViewController { func f() } class MyViewClass: UIViewController, MyViewProtocol { let value = 0 func f() { Task { print(value) // Cannot use parameter 'self' with a non-sendable type 'MyViewClass' from concurrently-executed code } } } @MainActor class MyOtherViewClass: UIViewController, MyViewProtocol { let value = 0 func f() { Task { print(value) // 何も出力されない } } } (edited)
Avatar
これはわからんですね、UIViewControllerのextensionに書いても出るし、ベースクラスを自前のにしたらMainActorもMainActor(unsafe)も全て警告が出るようになりました
😅 1
Avatar
もしかして、↓の self?.state も本来ダメなんでしょうか・・・。 final class UserViewController: UIViewController { private let state: UserViewState ... override func viewDidLoad() { super.viewDidLoad() ... let task = Task { [weak self] in guard let state = self?.state else { return } // この self もダメ?🤔 for await _ in state.objectWillChange.values { guard let self = self else { return } // state を View に反映する処理 self.nameLabel.text = state.user?.name } } cancellables.insert(.init { task.cancel() }) } ... } Task { } の外側で let state = self.state しておくのがいいのかな。 stateUserViewState )は @MainActor が付与されてるから Sendable になるはず。
4:09 AM
あれ?違うか。 VC は @MainActor だからいいのか。 (edited)
4:12 AM
これ↓も本来 MyViewClassMainActor だから警告出ないのが正しい? print(value) // Cannot use parameter 'self' with a non-sendable type 'MyViewClass' from concurrently-executed code (edited)
Avatar
警告出るべきじゃないよな〜とは思うんですが、protocol周りのActor対応は結構おざなりな感じがしてるので、まあ何が出てきても不思議ではないかなと言う感じがします
Avatar
actor contextの引き継ぎとsendable周り、何が意図された正しい挙動なのか混乱する・・・。
Avatar
これ↓も本来 MyViewClass が MainActor だから警告出ないのが正しい?
僕も出ないのが正しいのかなと思ってます。それが今は警告出てきて、さらに@MainActor付けると消える理由がわからなくて、「何が正しいんだっけ?」な状態です😅 ちなみにSwiftUIのViewでも同じことが起きます(@MainActorを付けると警告が消える)
(edited)
Avatar
おおお、 @MainActor は値型にも付けれるんですね・・・。個々のメンバにかかってるからいいのか。
Avatar
Authors: Pavel Yaskevich, Holly Borla Status: Awaiting implementation Introduction As a step toward the goal of improving the UI of generics outlined in Improving the UI of generics, we’d like to propose a couple of improvements that bridge the syntactic gap between protocols and generic types, and hide some of the complexity (both visual and...
3:35 AM
Protocolのassociatedtypeにprimary associatedtypeという概念を追加して
3:35 AM
Collection<Int> のように、アングルブラケットで指定できるようにする構文の提案
3:36 AM
generic parameterとassociated typeが紛らわしくなるし将来generic protocolの構文を実装する余地がなくなるから微妙だと思う・・・
Avatar
そのままウッカリgeneric protocolとして実装されて欲しい
Avatar
ABIとか型推論とか与える影響がありすぎるのでそれはないw
Avatar
Kishikawa Katsumi 10/27/2021 6:39 PM
https://developer.apple.com/documentation/xcode-release-notes/xcode-13_2-release-notes
You can now use Swift Concurrency in applications that deploy to macOS 10.15, iOS 13, tvOS 13, and watchOS 6 or newer. This support includes async/await, actors, global actors, structured concurrency, and the task APIs. (70738378)
6:39 PM
ついにConcurrencyのバックデプロイが使えるようになるらしいよ
🎉 3
Avatar
思ったよりずっとはやい
Avatar
Kishikawa Katsumi 10/27/2021 6:39 PM
来月くらいから申請できるのかな?
6:40 PM
少なくとも来年すぐくらいには使っていけそう
Avatar
あとはSendable周りの彼是が良くなっていけばかなり快適になりそう
6:42 PM
SendableをExistentialとして使うとbad accessが出まくるというのをこの間踏んでしまった
Avatar
Kishikawa Katsumi 10/27/2021 6:59 PM
https://twitter.com/dgregor79/status/1453432581622362112 複雑なことしてるから使ってバグレポートしてほしいとのこと
Please try this out and file bugs, then tag us on Twitter with Feedback numbers or SR numbers. It’s an enormously complicated feature to back-deploy and there may yet be issues we didn’t uncover. https://t.co/kmt97rXyV1
Avatar
Twitterが正規のレポート手段だったのか…
Avatar
Kishikawa Katsumi 10/27/2021 7:00 PM
Twitterすごい
Avatar
べんり
Avatar
We’re thrilled to announce a new open-source package for the Swift on Server ecosystem, Swift Distributed Actors, a complete server-oriented cluster library for the upcoming distributed actor language feature!
7:19 AM
3年前から内部で開発されてた分散アクタークラスタ用のフレームワークが、言語機能のdistributed actorによってAPIが洗礼されて、ついに公開された
Avatar
あれ、そんなアツい話が書いてあるのか。冒頭だけ読んで後回しにしてた
Avatar
Avatar
Yuta Saito
3年前から内部で開発されてた分散アクタークラスタ用のフレームワークが、言語機能のdistributed actorによってAPIが洗礼されて、ついに公開された
これはリポジトリのログ見て判明した
Avatar
Kishikawa Katsumi 11/4/2021 7:39 AM
viewDidLoad()awaitしようとしたらasyncにしないと呼べない、、、と思ったけどTask.detachedで包んでこう書くのね。根っこまでasyncかどうかをコンパイラがチェックしてくれるのはかなり良い。 override func viewDidLoad() { super.viewDidLoad() Task.detached { var req = URLRequest(url: URL(string: "")!) req.httpMethod = "POST" do { let data = try await URLSession.shared.data(for: req, delegate: nil) ... } catch { print(error) } } }
Avatar
actor context を引き継ぐなら Task { } だと思います。
Avatar
Kishikawa Katsumi 11/4/2021 8:01 AM
なるほど! Task { } だとURLSessionのコールバックでMainQueueにディスパッチ、したときと同じ挙動になるんですね。
8:02 AM
元のActorってことか。UIで使う場合はそのほうが絶対にいいですね。
9:30 AM
@Sendable closure は通常 actor context を引き継がないんですが、 @_inheritActorContextTask.init の場合は引き継ぐようになってるんですよね。ややこしい・・・。
9:32 AM
他にもめっちゃいっぱい付いてる😅 @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> Success
Avatar
Kishikawa Katsumi 11/4/2021 11:51 AM
むむ、後で読みます 🙏
Avatar
わかったと思ったけど、またわからんくなってきた。 DispatchQueueasync に渡すクロージャは @Sendable 付いてないんだけどいいんだっけ?過渡期だから付いてないだけ??
Avatar
過渡期だと思いますよ
👌 1
8:24 AM
現存する@escapingの9割はSendableであるべき、と思います
Avatar
そうですね。かなりの割合は @Sendable である必要がありそうです。 @Sendable でなくていいのは↓みたいなやつという理解。 struct Converter { let convert: (Int) -> Int init(convert: @escaping (Int) -> Int) { self.convert = convert } }
Avatar
合成関数の生成とかはSendable要らないですね
👍 1
8:29 AM
ただし、Sendableやescapingを伝播させる仕組み(rethrowのような)は無いと、今後キツくなっていくと思います (edited)
8:30 AM
Converterは、Sendable用のConverterを別途用意しないと成り立たない気がする
Avatar
たしかに
Avatar
クロージャそのものを型パラとして見れるようにして、Sendableの場合のconformingを作らないといけない
8:31 AM
この辺は今の型システムだと埋め切れてなくて、将来的に何とかなって欲しいなと言う感じがしますね
8:32 AM
というか、関数を@Sendableにして、型へのconformingから逃げてしまったのは
8:32 AM
実は負債に成り得るんじゃないか、と思ったりした
Avatar
struct Converter<F: (Int) -> Int> { let convert: F init(convert: @escaping F) { self.convert = convert } } extension Converter: Sendable where F: Sendable {} こう書けるようになりたい
Avatar
わかる
8:33 AM
実は、@Sendableじゃなくて、Callableの筋から頑張るのが正解だったんじゃないか?
Avatar
actorSendableConverter を渡したとして、それを利用するときに @Sendable クロージャが呼び出されると actor context がぶった切られる?
8:35 AM
いいのか、戻り値を利用するだけだから。
8:35 AM
クロージャの中は関係ないのか。
8:35 AM
そもそもクロージャの中は actor の外で宣言されていて、引き継ぐも何もないのか。
8:38 AM
struct Converter: Sendable { let convert: @Sendable (Int) -> Int } let converter: Converter = .init { // ここは何の context で実行される?? $0 * $0 } actor A { func foo(x: Int, converter: Converter) { print(converter.convert(x)) } }
Avatar
Converter、事実上CombineのCancellerと等価ですが、であるならば常にSendableで良い気がしてきた
12:33 PM
等価の事例にAsyncStreamのterminationクロージャがありますが、これはSendableですね
Avatar
Hello Swift Evolution! I recently started a discussion about easing the learning curve of introducing generic parameters. In that discussion, it was brought up multiple times that the existing syntax of existential types is actively harmful, and we should consider making the implications explicit in the language. I wrote up a proposal for intro...
7:17 AM
anyキーワードのピッチじゃあー
Avatar
いいね
7:24 AM
このレベルの変更入れられるなら、trailing closureのラベル周りも何とかなったりしないだろうか
Avatar
Enforcing that existential types use the any keyword will require a source change. To ease the migration, I propose to start allowing existential types to be spelled with any with the Swift 5.6 compiler, and require existential types to be spelled with any under the Swift 6 language mode. 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.
7:26 AM
古い記法を5系では有効、6系では無効、機械変換できるのでヨシ
Avatar
ヨシ
Avatar
ホントかなァ
Avatar
マイグレーター、コーナーケースで壊れがち
7:27 AM
コンパイル可能な状況なら理論上書き換え可能なのは、そう。
Avatar
Avatar
tarunon
このレベルの変更入れられるなら、trailing closureのラベル周りも何とかなったりしないだろうか
そうだね、第一クロージャのラベルも、5系では記述可能、6系では必須ってしてほしい
Avatar
単体で見たときは大丈夫だが、swift6はこの変更だけではないから
7:28 AM
組み合わせで死ぬ、は有り得るけど
Avatar
お、たしかに。
Avatar
まあこの変更はあるべきだから、最悪壊れても良いよ
Avatar
いや、でも、
7:29 AM
anyを付与する変更は、まだ、5.6としてvalidなコードだから
7:29 AM
コンパイルできる状態を維持して次のマイグレーターをかけられるはず
Avatar
大体カチキレてる人間は互換のある間に仕事を済ませないで、後に引けなくなったときに全部やろうとして失敗するんだ
7:29 AM
夏休みの宿題ってヤツだな
Avatar
古いマイグレータを搭載したXcodeが起動できなくなったら詰むのかな
Avatar
Xcode12は実質IntelMacでしか動かないからわりと早く淘汰されそう
Avatar
Kishikawa Katsumi 11/17/2021 7:46 AM
古いコードが動かないことによる損失は私はもっと大きいと思うのでもうちょっとがんばってほしいと思うな。別のキーワードにしたらいいんじゃないか。
Avatar
Avatar
Yuta Saito
古いマイグレータを搭載したXcodeが起動できなくなったら詰むのかな
うわっ、なるほどっ
Avatar
Avatar
Kishikawa Katsumi
古いコードが動かないことによる損失は私はもっと大きいと思うのでもうちょっとがんばってほしいと思うな。別のキーワードにしたらいいんじゃないか。
別のキーワードだとしても、「現状のキーワードなしを違反文法とする」という変更が、破壊的であるのは変わらないですよ
Avatar
Kishikawa Katsumi 11/17/2021 7:49 AM
そうなのか。Breaking Change不可避の変更なのね。
Avatar
5.6までは「現状のキーワードなしも許す」にしておくからそこで移行しなさいというプラン
7:50 AM
岸川さん的な立場からは「6.0からは違反とするのはやめろ」って意見がいいですね
7:50 AM
6.0でも警告が出るだけでも自分は構わないな〜
Avatar
本命はExistemtialの記法が確立することで、extension any P: Pが書けるようになることだと思うけど
Avatar
Kishikawa Katsumi 11/17/2021 7:52 AM
だいたい読んだ。ちょっと勘違いしていた。
Avatar
それは別にコンパイルエラー無くても新記法さえ存在すれば実現できますよね (edited)
Avatar
Kishikawa Katsumi 11/17/2021 7:52 AM
もともとの文法はそのままでany追加、でいけないのかな。
7:53 AM
それは別にコンパイルエラー無くても新記法さえ存在すれば実現できますよね
^ これこれ
7:53 AM
つまり「6.0からは違反とするのはやめろ」ということか。
Avatar
Avatar
tarunon
それは別にコンパイルエラー無くても新記法さえ存在すれば実現できますよね (edited)
それだけなら extension any P: P {} という記法だけ導入する手があるね。(このanyは Pではなくextensionにかかっている) (edited)
Avatar
6.0から違反(エラー)にしなければいけない理由ってあるんですかね。警告でいいようにも思うんだけど。そしてわかっている人が明示的にその警告をオフにできるコンパイラオプションがあるとなおうれしい。 (edited)
Avatar
Avatar
hironytic
6.0から違反(エラー)にしなければいけない理由ってあるんですかね。警告でいいようにも思うんだけど。そしてわかっている人が明示的にその警告をオフにできるコンパイラオプションがあるとなおうれしい。 (edited)
理論上はないと思います どちらも使える状態を維持するのはコンパイラの保守コストが上がってつらい、とかはあると思います
Avatar
Avatar
omochimetaru
理論上はないと思います どちらも使える状態を維持するのはコンパイラの保守コストが上がってつらい、とかはあると思います
ああ、保守コストはたしかに。
Avatar
Kishikawa Katsumi 11/18/2021 8:28 PM
Hi all! This post discusses an enhancement to Swift-DocC and Swift-DocC-Render that will allow developers to build DocC archives that can be hosted without custom routing. This is specifically designed to enable DocC to be used in additional static hosting environments, most notably GitHub Pages. This change is meant as a quick solution to add...
👀 3
8:28 PM
doccを静的にホストできるようにするための議論かな
Avatar
@giginet がGitHub Pagesで使いにくいって言ってたやつかな
👀 1
Avatar
Kishikawa Katsumi 11/20/2021 3:12 AM
すべてのアクセス可能なパスにindex.htmlファイルを置く、ということでrewrite不要にするってことらしい。 けっこう大がかりだなと思ったけど好印象なコメント多い。
Avatar
doccってstatic hostingにうまいこと対応してない...?
Avatar
すぐ上に話題ありますね
t_yasashii 1
Avatar
まだそうはなってないという話
Avatar
なんか、意外だな。ちゃんとみておけばよかった。
Avatar
みてきた
6:52 AM
なるほど...
6:53 AM
Vexil (named for Vexillology) is a Swift package for managing feature flags (also called feature toggles) in a flexible, multi-provider way. - Vexil/generate-docs.sh at main · unsignedapps/Vexil
6:54 AM
こういう感じなのか...
Avatar
↑はなんか凝った事も追加でやってそうですね
Avatar
ファイルコピーしてるだけにみえるけれど...
7:01 AM
https://vexil.unsignedapps.com/documentation/vexil/ 出力はこんな感じになってる
Avatar
# Re-create the .json structure inside /documentation find "${WORKING}/data" -type f -name '*.json' \ | sed 's%data/%%g' \ | sed 's%\.json%%g' \ | xargs -n 1 mkdir -p # Copy our website root files over the top too cp "${WEBSITE_DIR}/index.html" "${WORKING}" cp "${WEBSITE_DIR}/styles.css" "${WORKING}/css" cp "${WEBSITE_DIR}/vexil.svg" "${WORKING}/img"
7:03 AM
↑このへんは非標準に見えます
Avatar
cp -R "${VEXILLOGRAPHER_DOCCARCHIVE}"/data/documentation/* "${WORKING}/data/documentation/"
7:04 AM
なので、もともとdocarchiveにあるjsonを元にディレクトリつくってる感じ? (edited)
Avatar
Contribute to waiwai-swiftc/waiwai-docc development by creating an account on GitHub.
7:07 AM
ぎぎにゃんのサンプルはもうちょっとシンプルだけど、 デプロイのところは含まれてないから、アーカイブしてから色々コピーするという感じにはなりそう
Avatar
そんな感じですねえ
7:08 AM
index.htmlを配置とか、フォーラムの提案をhackyだって言ってる人がいるけどまあそうだと思う
Avatar
Kishikawa Katsumi 11/25/2021 12:34 PM
@MainActor を書いたクラスはバックポートされるXcode 13.2betaを使わなくてもiOS 14以前で動くんですね。コンパイルエラーにもならない。
Avatar
async呼ばなければタダですね
Avatar
Kishikawa Katsumi 11/25/2021 1:10 PM
そうなんですねえ。
Avatar
これで思い出したんですけど、Rustの場合はサスペンションポイントをまたいで値を共有したい場合、その値はSendトレイトを実装している必要があるんですよね。 Swiftはその制約が無いけど、既にどこかで議論されてたりするのかな? https://discord.com/channels/291054398077927425/430242233468452865/915087485640511598
Avatar
ええ、そうなんだ。Rustの場合はそのコールスタックでしかvalidでないポインタとかが出てくるからかな?
4:55 AM
Swiftの場合それに該当するのは inout T 型だけど、 これは async 関数だと使えないから、出てこないので
4:55 AM
Swiftの値はどんな値も suspension point 間を move していけることは保証されてるので必要ない気がする。
Avatar
たとえばこうすると2スレッドから同時にSendableでない値sにアクセスできちゃう気がするんですよね。 import Foundation func g() async {} func f(s: NSMutableString) async { Thread.current.threadDictionary["str"] = s await g() Thread.current.threadDictionary["str"] = s } (edited)
5:01 AM
@swift-main -warn-concurrency import Foundation func f(s: NSMutableString) async { DispatchQueue.main.async { print(s) } }
Avatar
Avatar
Yuta Saito
@swift-main -warn-concurrency import Foundation func f(s: NSMutableString) async { DispatchQueue.main.async { print(s) } }
swiftNightly BOT 11/30/2021 5:01 AM
stderr:<stdin>:5:15: warning: cannot use parameter 's' with a non-sendable type 'NSMutableString' from concurrently-executed code print(s) ^ Foundation.NSMutableString:1:12: note: class 'NSMutableString' does not conform to the 'Sendable' protocol open class NSMutableString : NSString { ^
Avatar
これがワーニング出るんだったらサスペンションポイント跨ぎでスレッド変わるパターンもダメじゃないですかね
Avatar
actor contextに守られてるスコープではスレッド変わっててもアクセスが常に並行になるから大丈夫というわけではなく?
Avatar
そもそもactor context外での並行アクセスは常に非安全か
Avatar
Avatar
Iceman
actor contextに守られてるスコープではスレッド変わっててもアクセスが常に並行になるから大丈夫というわけではなく?
直列だから大丈夫、じゃない?
Avatar
Avatar
omochimetaru
直列だから大丈夫、じゃない?
同時にアクセスが起こらない的な意味で発言しましたが直列のほうが正しいんでしょうかね?
Avatar
並行というのは同時に起きることをさすので
7:09 AM
時系列的にかぶらないことを言うなら直列です
Avatar
それは並列ではないですか?
Avatar
あー並列と並行を意識して使い分けていたのか
7:13 AM
並列計算(へいれつけいさん、英語: parallel computing)は...複数の処理装置(プロセッサ)上でそれぞれの処理を同時に実行させることである[1]。 並行計算(concurrent computing)は一つのタスクの計算を並列化することにとどまらず、複数の相互作用しうるタスクを、プロセスやスレッドなどをもちいて単一または複数の計算資源にスケジューリングするといった、より汎用性の高い処理をさす。
(edited)
7:14 AM
物理的に実際に同時に複数の計算を行うのが並列(parallel)で、 もしかしたら1コアの状況でも時分割して見かけ上同時に実行するのが並行(concurrent)であると。 (edited)
7:16 AM
それで、actor isolatedな処理は、一つのactorでは常に一つの実行しかされず、スレッド並行という意味でも起こらないので、並行実行も並列実行もされない、と思います。 (edited)
Avatar
複数のactor context内にキャプチャされた変数へのアクセスはその変数から見たら直列なアクセスではありますが、プロセス全体から見たら並行なアクセスに見えるなぁとも思ったのですが、こういう場合でも並行とは言わないんでしょうかね
Avatar
プロセス全体では複数のactorが並行で実行されているのがSwift Concurrencyだと思います、それは言うと思う。 でも並行というのはマルチスレッドなどによって見かけ上同時に実行することを言うので、 同じactor contextで保護されている変数に見かけ上同時にアクセスが起きないことを言う場合は、 「actor contextの元で直列化されているので大丈夫」になると思います。 (edited)
Avatar
自分でも言ってて単一の変数の保護の話をしてるのにプロセス全体からの視点を持ち込む意味がよくわからないと思ったので、今度から直列と表現します
7:30 AM
僕の勘違いはこの記事が指摘してる通りの内容のような気がする https://zenn.dev/koron/articles/3ddcaaeae37f9befdf70
Avatar
並列と並行 / 多言語からみるマルチコアの活かし方に見られるように並行(concurrent)とは「複数の処理を順番に実行すること」とする誤った記述を、この記事に限らずチラホラ目にします。
ふむふむ。。 並行というのは(物理)並列に対して、スレッドなどによる仮想的な方法による同時実行も含めてより抽象化した言葉で、同時実行が主たる意味なのは同じなんだけど、 その実現方法の一つであるプリエンプティブマルチタスクなCPUのスケジューリングの概念を拡張しちゃって、 「非同期な処理をコードの制御上順番に実行する」事を指しているという誤解がある・・・?
7:39 AM
しかし、批判されている記事に60いいねついていてコメント欄にツッコミが無いのはちょっと気になるな。
Avatar
omochimetaru 12/1/2021 8:29 AM
Now that the stdlib no longer needs ICU, let&#39;s drop the dependency 🙂 This is marked as a draft because right now this only removes the immediate dependency on the stdlib, and isn&#39;t ...
8:29 AM
Now that the stdlib no longer needs ICU, let's drop the dependency 🙂
8:29 AM
@Yuta Saito ↑これどうやってん
Avatar
全部再実装
Avatar
omochimetaru 12/1/2021 8:30 AM
すごい
Avatar
Azoyさんがしばらくコツコツやってましたね
8:31 AM
This is still a wip, but wanted to get some benchmarks and tests ran on this. Resolves: rdar://51635207, https://bugs.swift.org/browse/SR-9432
8:32 AM
すごい
Avatar
気合だ
Avatar
omochimetaru 12/1/2021 8:34 AM
互換性本当に取れるのか
8:35 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
8:35 AM
Swiftで書かれたC++コード生成機がある・・・
Avatar
ブートストラップ…
Avatar
omochimetaru 12/1/2021 8:36 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
8:37 AM
swiftpm packageになってる!
8:37 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
8:37 AM
8:37 AM
やべえ
8:38 AM
UnicodeData.txtも1.7MBある
8:39 AM
これは凄いなあ
Avatar
これでSwiftに必要な部分だけが抽出できたからサイズ最適化もやりやすくなりそう
Avatar
omochimetaru 12/1/2021 8:40 AM
ICU全体よりは持ってるデータやロジック量は減る?
Avatar
流石に減るんじゃないですかねぇ
Avatar
omochimetaru 12/1/2021 8:42 AM
結局コードポイントに関する辞書が支配的そうな気もするけど
Avatar
ICUの方でも埋め込むデータを削減するための仕組みがあって、Wasmではそれ使って既に削ってるのでそこまで減らないかも https://unicode-org.github.io/icu/userguide/icu_data/buildtool.html (edited)
Avatar
omochimetaru 12/1/2021 8:43 AM
へえ〜
Avatar
昔の実験の記録によると文字セット変換用のマッピングデータが大きかったみたいです
Avatar
omochimetaru 12/1/2021 8:49 AM
文字セットって、sjisとeucの対応みたいな? (edited)
Avatar
そうそう
Avatar
omochimetaru 12/1/2021 8:50 AM
なるほど。それは確かに重そうだ。
Avatar
そうか、Unicodeだけじゃダメなのかぁ・・・。
Avatar
omochimetaru 12/1/2021 8:50 AM
Foundation使うとsjisバイト列とか作れるけど、
8:51 AM
FoundationはICUをリンクしてるままってこと?
Avatar
そこはそのままなんじゃないですかね
Avatar
omochimetaru 12/1/2021 8:51 AM
あれ、そうすると、バイナリサイズはでかくならないか?
8:51 AM
stdlibだけなら小さくて済むけど
Avatar
たしかに
Avatar
単純に考えるとでかくなりそう。
Avatar
omochimetaru 12/1/2021 8:51 AM
FoundationのICU部分と、再実装したUnicode部分が、冗長になる
Avatar
どうするんだろう
Avatar
omochimetaru 12/1/2021 8:52 AM
www 大変そうだ・・・
Avatar
確かにFoundationでもsjis作れるのか
Avatar
omochimetaru 12/1/2021 8:54 AM
お仕事でやりましたね
8:54 AM
サーバーサイドSwiftから、Windowsエクセルで安定する生成CSVをダウンロードさせたくてね
Avatar
なんかうまくいかなくて自分はiconvでやってました (edited)
Avatar
Hello Swift community, The review of SE-0335 " Introduce existential any" begins now and runs through December 22, 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 r...
👏🏻 6
Avatar
Hi everyone. The review of SE-0336, "Distributed Actor Isolation", begins now and runs through December 22, 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 messaging the review m...
10:24 AM
distributrd actorの正式レビューもはじまったのか、すごい
10:29 AM
0335の動機の章は、ワカリが強くて良い文章だなあ
Avatar
Distributed Actor、↓のスレッドが興味深かったけど、コメントや判断できるほどの知見がなかった。 https://twitter.com/1amageek/status/1466656781774761984?s=21 (edited)
@xuwei_k @rizumita 重要なのは 1. Apple Siliconが分散システムにも対応できるように作られていること 2. Swiftが分散システムにおける実装を安全にかけるActor Modelを導入してること 3. Swiftがクライアントとサーバーで利用できること 4. Swiftがプロトコル指向であること などが相まって、やばいって話なので
Avatar
any P.Typeと(any P).Typeと(any P).selfはややこしいけど、じっくり眺めてると、素直な定義でしっくりくるな
Avatar
Erlang の actor とかは最初から distributed だし、特別なものと思ってなかったけど、クライアントサイドで実際に使われている言語& Apple Silicon 的な視点の話は聞いたことがなかったので。まだ Distributed Actor については Proposal 等何も読んでないので書いてあるのかもしれないけど。
Avatar
Erlangはマイナーだけどその論点ならScala akkaも満たしてるんですよね
10:44 AM
Swiftはそれに加えてasync awaitと統合されてる事が新しいと思います (edited)
Avatar
Scalaはクライアントサイドであんまり使われない?
Avatar
Androidで使われた時期もあったけどKotlinになりましたね
10:45 AM
でもデスクトップクライアントなら全然いけるとおもいます
Avatar
Apple Siliconが分散システムにも対応できるように作られていること
この文脈だと JVM がダメ?
Avatar
そのくだりは僕はよくわかんないです 誰もまだAppleシリコン最適化バキバキのハイパフォーマンス分散システムを実戦投入してないと思う。
10:47 AM
まあこの前のワイワイで雑談にでてたIntelよりArmの方が参照カウンタの処理が早いからSwiftに有利、みたいな話はありましたね (edited)
10:48 AM
まあJVMだとどうしてもオーバーヘッドは少しはあるから、ネイティブ言語でトップスピードに期待できる、とかは言えるのかも
Avatar
仮に Apple Silicon が効いたとしても、クライアントサイドが Apple Silicon オンリーにも、 Swift オンリーにもならないという問題はありそうだなぁ。でもクライアントサイドもサーバーサイドも Actor で統合された夢の世界もあり得るのかなぁ。
Avatar
いわゆるモバイルアプリのクライアントがactorになってても、現状のJSON APIと大して使い心地は変わらないと思うんですよね (edited)
10:51 AM
どういうシステムにアクターがマッチするのか、という議論が重要なんじゃないか
Avatar
DB が Distributed Actor でラップされたら、アプリから直接 Firestore にアクセスするくらいの感覚で DB 直接触れたりするんだろうか? (edited)
Avatar
どういう感覚の部分ですか?
Avatar
API を介したやりとりの部分が消失して、直接やりとりしているような感じになるとか。
Avatar
個人的には、Actor自体がSendableな事が強みな気がしています 通信先のノード数が変動するような状況で、扱いやすくて便利になるというか。
Avatar
Avatar
koher
API を介したやりとりの部分が消失して、直接やりとりしているような感じになるとか。
それはトランスポートの実装をActorに任せられて楽、って話に見えますけど、使う側のユーザーからすると特にコードも変わらないような気がするんですよね
10:57 AM
SQLを引数に渡して、レコードが返ってくるasync funcなのは、同じ事なので。
10:57 AM
リモートにあるステートフルなオブジェクトを、そうと意識せずに、普通のclass instanceだと思って取り回せるところが、distributed actorの価値だと思う。
Avatar
そうなったときに、リモート(サーバーサイド)にある DB の actor をローカル(クライアントサイド)から触れることで、 API を介したやりとりのレイヤーが消失したりしないかな?
Avatar
APIを介するレイヤーって、実装詳細じゃないですか? もともとactorがなくても、メソッドにラップできるので。
11:02 AM
そのラップする作業をdistributed actor transportがやってくれるから手間が減らせるというのはわかりますが、 あれも結局アクターのためにAPI操作を自動生成してるにすぎないので、話の構造が同じに見えるんです
11:03 AM
(distributed actorを使うためには、メソッドに対応したリクエスト型を定義して、受信側でメソッド呼び出しに転送するコードを、生成します (edited)
Avatar
うーん、でもたとえば、仮に関数を呼び出すために直接インスタンスを渡せなくて、一度 JSON にエンコードした Data を渡して、それを受け取った側でもデコードして扱わないといけなかったという状況から、直接インスタンスを渡せるようになったくらいのインパクトはあるんじゃないかな?
11:05 AM
メソッドに対応したリクエスト型を定義して、受信側でメソッド呼び出しに転送するコードを、生成します
そうなのか。
Avatar
それはアクターのメリットじゃなくて、アクターのためにコンラッドさんが用意したコードジェネレーターが便利って話で
11:05 AM
今までも同じ事はできたと思うんですよね。
11:06 AM
で、それは元のツイートで吉田さんが書いている、これまでのRPCと何が違うのか?という問いが指摘してるポイントだと思います
Avatar
Avatar
koher
メソッドに対応したリクエスト型を定義して、受信側でメソッド呼び出しに転送するコードを、生成します
そうなのか。
Swiftのdistributed actorは、実際の通信方法が言語機能から分離されているので、そこをJSON/HTTPにしたり、gRPCにしたり、ユーザーが選択できます。ここは面白いですね。
Avatar
うーん、 API の消失というのは単にエンコード・デコードが省略できるというだけの意味ではなくて、
リモートにあるステートフルなオブジェクトを、そうと意識せずに、普通のclass instanceだと思って取り回せる
ということによって、より自由に API の向こう側とこちら側を行き来できる感じかなぁ。
Avatar
Avatar
koher
うーん、 API の消失というのは単にエンコード・デコードが省略できるというだけの意味ではなくて、
リモートにあるステートフルなオブジェクトを、そうと意識せずに、普通のclass instanceだと思って取り回せる
ということによって、より自由に API の向こう側とこちら側を行き来できる感じかなぁ。
例えば、distibuted funcの引数にactorを渡す事ができるようになるんですが、 (edited)
11:10 AM
これは確かに従来のAPIだとできないんですが、
11:11 AM
例えばactor ChatMessageみたいなものを引数に渡してしまうと
11:11 AM
サーバー側でawait chatMessage.textが必要になって、無駄な往復通信が起きます
11:11 AM
だから結局アンチパターンになると思います
Avatar
リモートに渡された actor は実体が渡るのではなく、アクセスするときは必ず通信が発生するってこと?
Avatar
そうです。アクターがトランスポートを通るときは、インターネットアドレスとしてシリアライズされます
Avatar
なるほどー。まあそうじゃないと同期できないよなぁ。
Avatar
アクター自体は常に産まれたホストマシンに存在しています
11:13 AM
リモートからみたときに、実は同じホストマシンにいるのか、リモートマシンにいるのかの見分けがつかないというのがマジックなところ。 (edited)
11:14 AM
あーだからそうですね、NoSQLみたいな環境で、データベースが複数あるときに、それぞれのレコードが自身のDBホストに実在するactor、みたいなスタイルは面白いかも
11:15 AM
P2Pのサンドボックス環境とかにも向いてるのかな?
Avatar
アプリ同士が P2P で actor でやりとりするとかもできるのかな?
Avatar
今流行りのメタバースの実装に向いてるのかもw
Avatar
Avatar
koher
アプリ同士が P2P で actor でやりとりするとかもできるのかな?
できますできます。
Avatar
それはかなりおもしろそう。
11:16 AM
最初に actor を相手に渡すところがイメージできてないけど。
Avatar
最初のクラスター参加にはサービスディスカバリーの仕組みが何かしら必要です。
11:18 AM
Distributed actors transport example, for feature review - swift-sample-distributed-actors-transport/SampleApp at main · apple/swift-sample-distributed-actors-transport
11:18 AM
一番最初って確かにどうすればいいんでしょうね?↑のどこかにあるはず
11:19 AM
let remoteRoom = try ChatRoom.resolve(room.id, using: chatter.actorTransport) try await chatter.join(room: remoteRoom) }
11:20 AM
見て思い出した。resolveメソッドを使うんだ。 (edited)
11:20 AM
その引数のIDを、何らかの方法で手に入れればいい。
11:21 AM
このIDの正体は、トランスポートの実装次第だけど、大体のケースではIPアドレスとポートとインスタンスIDだろう。
Avatar
resolvedistributed actor に生えてる static メソッドなのか。
Avatar
そう
11:23 AM
さっき言ってた、アクターがトランスポートを通り抜ける時に、これを活用してる。
Avatar
DistributedActorSystem の実装側が大変そうだ・・・。
Avatar
associatedtype ActorSystem: DistributedActorSystem
11:26 AM
ActorSystemってなんだろう。前読んだ時にはActorTransportって書いてたやつなことかな。
Avatar
Avatar
koher
DistributedActorSystem の実装側が大変そうだ・・・。
デフォルトのこれを使っとけばいいってことなんじゃないかしら https://github.com/apple/swift-distributed-actors ディスカバリ部分はどのくらい手間かかるのか気になりますね。
Peer-to-peer cluster implementation for Swift Distributed Actors - GitHub - apple/swift-distributed-actors: Peer-to-peer cluster implementation for Swift Distributed Actors
👀 1
Avatar
protocol CodableDistributedActorSystem: DistributedActorSystem { typealias SerializationRequirement = Codable }
12:12 PM
typealiasの右辺にプロトコル書くのってありなんだっけ?
Avatar
existentialがprotocolにconfirmしてるならいける
12:13 PM
Errorはいけてる
12:13 PM
はず (edited)
12:15 PM
あーー
12:15 PM
Codableは難しそうだな
Avatar
それはプロトコルを書いてるというよりany Pを書いてるってことよね
12:22 PM
ここ、associayedtypeじゃなくて、associatedprotocolみたいな新しい構文にしたほうが良い気がする
Avatar
associatedprotocolって、そうしたらそれはgeneric protocolになるのでは🤔
1:09 PM
と言うかそうした方が色々具合が良い気がする…
Avatar
Avatar
tarunon
と言うかそうした方が色々具合が良い気がする…
omochimetaru 12/9/2021 1:11 PM
generic protocolではまるかな? これちょっと特殊な扱いなんだよね
1:13 PM
distributed funcの引数と返り値がそのプロトコルを満たしてないといけないっていう特殊な検査をする
Avatar
あーーー
1:31 PM
難しいね
1:31 PM
Higher Kinded Typeの方が近いかも?
1:32 PM
いやちょっと違うか
Avatar
Kishikawa Katsumi 12/10/2021 9:35 AM
https://developer.apple.com/forums/thread/696197 自分で使ってなくてもConcurrencyを使ってるライブラリがあると14以前で起動できない問題。 以前もFoundationをweak_linkしないといけない問題とか何かあったけど、こういう暗黙的にリンクされる標準のフレームワークをweak_linkしないといけないっていうのを気づくのはだいぶ難しいな。
Avatar
13のサポートを落とす...
Avatar
Kishikawa Katsumi 12/10/2021 9:43 AM
14もですよね。けど実際それはアリですよね。13から15にアップデートできないデバイスはなかったと思うので。iPadはもしかしたらあるんだっけか。
Avatar
いや、なかったと思う
Avatar
Kishikawa Katsumi 12/10/2021 10:11 AM
お、それならみんなでサポートバージョンを上げるのができれば一番いいですね。
Avatar
Hey everyone! Attached inline below is a proposal to add a move function to the swift stdlib that possesses a use after move diagnostic. The full eternal URL is https://github.com/gottesmm/swift-evolution/blob/move-function-pitch-v1/proposals/000a-move-function.md Thanks in advance for any feedback/thoughts! You can try it out with the tool...
5:16 AM
moveも動いた!!
Avatar
これは嬉しい
Avatar
この変数はここで使うの終わりにしたい、ってことたまにあって、 varにして上書きしたり、shadowしたり、doスコープ切って終わらせたり、するんだけど、 moveがあるとシンプルに書けて嬉しい。
Avatar
doスコープ切って終わらせたり、するんだけど、 moveがあるとシンプルに書けて嬉しい。
これは同名で再宣言はできるのかな? do でスコープ切るときは、同じ名前で後で宣言したいことが結構多い気がする。
Avatar
なるほど。それはできない気がしますね。意味解析の順番が前後しちゃうので。
8:21 AM
理屈上は再宣言できるようにはできるけど、結構頑張らないとその機能は入れられないと思うから、特に書いてないのでそうならなそう。
Avatar
再代入の例はありましたね。でも再代入だからlet宣言できないかな func f() { var x = getValue() let _ = move(x) // Can't use x here. x = getValue() // But I can use x here, since x now has a new value // within it. }
Avatar
なるほどー。
Avatar
Avatar
Kishikawa Katsumi
https://developer.apple.com/forums/thread/696197 自分で使ってなくてもConcurrencyを使ってるライブラリがあると14以前で起動できない問題。 以前もFoundationをweak_linkしないといけない問題とか何かあったけど、こういう暗黙的にリンクされる標準のフレームワークをweak_linkしないといけないっていうのを気づくのはだいぶ難しいな。
Kishikawa Katsumi 12/11/2021 4:57 PM
このサードパーティライブラリがConcurrency使ってるとiOS 14以下で起動できないっていうの、RealmSwiftで起こってるわ。。。 Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Exception Note: EXC_CORPSE_NOTIFY Termination Description: DYLD, dyld: Using shared cache: EC12EBDC-CAE3-34EC-ACCB-0B6E5ABC73EB | dependent dylib '@rpath/libswift_Concurrency.dylib' not found for '/private/var/containers/Bundle/Application/5A5B9B8F-4D0F-478A-B25B-2CF006B1C7FA/Illustail.app/Frameworks/RealmSwift.framework/RealmSwift', tried but didn't find: '/usr/lib/swift/libswift_Concurrency.dylib' '/private/var/containers/Bundle/Application/5A5B9B8F-4D0F-478A-B25B-2CF006B1C7FA/Illustail.app/Frameworks/libswift_Concurrency.dylib' '/private/var/containers/Bundle/Application/5A5B9B8F-4D0F-478A-B25B-2CF006B1C7FA/Illustail.app/Frameworks/RealmSwift.framework/Frameworks/libswift_Concurrency.dylib' '@rpath/libswift_Concurrency.dylib' '/usr/local/lib/libswift_Concurrency.dylib' '/usr/lib/libswift_Concurrency.dylib' Highlighted by Thread: 0
😇 2
Avatar
この問題ってライブラリ側で#if availableを気を遣って書いても発生するんですか?
Avatar
Kishikawa Katsumi 12/12/2021 3:38 AM
Weak linkにしない限りは起こりそう
Avatar
#if canImport(_Concurrency) の場合、ランタイムにdylibが環境にあるかは保証できないのでダメ。 if @available(iOS 15) の場合でも、これはimport文には付けられないので、結局暗黙的な import _Concurrency は挿入されてしまって、autolinkで強リンクされるのでダメですね
Avatar
厳しいですね
Avatar
Kishikawa Katsumi 12/12/2021 3:39 AM
Weak linkは乱暴にいうと分岐して呼び出さなければ大丈夫という仕組みなので
Avatar
本来はドライバが、デプロイメントターゲットが14以下の場合は -weak-l_Concurrency を付けるべきなんですけど漏れてたのかな
Avatar
Kishikawa Katsumi 12/12/2021 3:41 AM
意外と身近に起こりそうで、単にライブラリアップデートで起こるのでQA飛ばしがち、みたいなこともありそうで難しい。
Avatar
ライブラリ提供者側で複数OS検証みたいなことも難しそうですしねぇ
3:45 AM
これまでもOSフレームワークのimportで似たような問題は起こり得たけど、今回のケースは暗黙的にimportが挿入されるから気がつけなさそう
Avatar
Kishikawa Katsumi 12/12/2021 4:44 AM
Bitcodeオフでも直るらしいんだけど、それがなんでなのか分からない
Avatar
Kishikawa Katsumi 12/12/2021 6:01 AM
CocoaPodsとSPMで試してみたけどweak linkされてるように見えるな。何か条件を見落としてるのかな。
6:04 AM
なるほどApp StoreかTest Flightで配布したときだけなのかな。ということはApple Sideで修正されるべきっていうのはそういうことか。App Store Connectでなんかしているってことか。なのでBitcode Offでも直ると。
Avatar
https://discord.com/channels/291054398077927425/291211035438874625/920563280509018114 で話してた話、やっぱ @MainActor なメソッドをオーバーライドする場合でも、暗黙的に @MainActor にならない方がいい気がするなぁ。 viewDidAppear とかでも、もし super.viewDidAppear(animated) するなら、そこで await して viewDidAppear の宣言に async を付けるか、 @MainActor を(メソッドまたはクラスに)付けるか選べる。
Avatar
そもそもはActorContextは暗黙で引き継いで、それとは別にActorContextを引っ剥がすアノテーションがあった方が良いのでは?という話でした
2:33 PM
今だと全て強制的に引っ剥がした上で改めて宣言しろ、となっているが、これは逆の方が勝手が良いのではないか、と
Avatar
Avatar
tarunon
そもそもはActorContextは暗黙で引き継いで、それとは別にActorContextを引っ剥がすアノテーションがあった方が良いのでは?という話でした
この実験によると、オーバーライド時は剥がされてなくないですか? https://discord.com/channels/291054398077927425/291211035438874625/920567683420930068
Avatar
オーバーライド関係なく、サブクラスのみに生やすメソッド含めて全てMainActorの扱いで良いのではと考えています
Avatar
逆に、オーバーライドでも @MainActor 扱いをしなくていいんじゃないかというのが https://discord.com/channels/291054398077927425/291054454793306112/920672645412962365 で言いたかったことですね。
Avatar
Swift's high-level semantics try to relieve programmers from thinking about memory management in typical application code. In situations where predictable performance and runtime behavior are needed, though, the variability of ARC and Swift's optimizer have proven difficult for performance-oriented programmers to work with. The Swift Performance...
2:17 AM
オーナーシップロードマップ!
Avatar
おおお….
Avatar
We will be posting pitches for the features described in this document over the next few months.
2:23 AM
非同期の次はオーナーシップのキャンペーンになるっぽいな
Avatar
Generalized nonescaping argumentsがアツそうだ
Avatar
コンパイラが挿入するretain/releaseが見える人向けのアトリビュート公式化きた https://forums.swift.org/t/pitch-formally-defining-consuming-and-nonconsuming-argument-type-modifiers/54313
Hey everyone! This is the consuming/nonconsuming argument type modifier pitch I was speaking about. The permanent URL is: swift-evolution/000b-consuming-nonconsuming.md at consuming-nonconsuming-pitch-v1 · gottesmm/swift-evolution · GitHub. For convenience I also attached it inline below. Formally defining consuming and nonconsuming argumen...
Avatar
オーナーシップ周りの一部かな?
3:19 AM
@sharedじゃなくて__sharedにするのかな (edited)
Avatar
ロードマップに出てきたconsmingの単体ピッチだ
Avatar
こんばんは。こういったコードを見かけたんですが、この記法(Selfを代入してるようでなんか違う)はなんという名前なのでしょう?うまくググれなくて困っておりまして。。。 public static let adaptiveWhite = Self { $0.userInterfaceStyle == .dark ? .isowordsBlack : .white } https://github.com/pointfreeco/isowords/blob/b87f4c61c0523564adf17c031f9fa4b88a40d631/Sources/Styleguide/Colors.swift#L4-L6
Open source game built in SwiftUI and the Composable Architecture. - isowords/Colors.swift at b87f4c61c0523564adf17c031f9fa4b88a40d631 · pointfreeco/isowords
Avatar
Classにクロージャを受けるrequired initが生えてるんじゃないでしょうか?
Avatar
あー、なるほど。
11:01 AM
Open source game built in SwiftUI and the Composable Architecture. - isowords/Color.swift at b87f4c61c0523564adf17c031f9fa4b88a40d631 · pointfreeco/isowords
Avatar
これ、親クラスがUINavigationControllerになるだけでSendableじゃないと言われてしまうんですがなにか分かる方いますか?
Avatar
これが関係しているかもしれません。 https://bugs.swift.org/browse/SR-15131 Xcode13.2.1だとwarning出ますが、2021-12-23のmain repoのsnapshotにしたらwarning消えました。UIViewController経由でMainActorになっているからとかなんですかね???🤔 (edited)
Avatar
確かに13.2.1から出たような気はしますね。明示的にMainActor指定してるからSR-15131の状況とは違いそうですが、その修正の巻き添えかなにかでこのパターンが壊れたのかなぁ
🤔 1
Avatar
その辺りチェックしているコードを追ってみようとしているのですが、いつも途中で迷子になるんですよね😂
Avatar
どなたかご存知の方がいらっしゃれば教えていただきたいのですが、-warn-concurrencyつけるとMainActor外で使われているUIKitのクラスのclassプロパティなどがエラーになるのですが、このsource breakingを回避する方法ないでしょうか? それともこういうエラーが出なくするまでは-warn-concurrencyはつけらないんですかね….
Avatar
@MainActor let willResignActiveNotification = UIApplication.willResignActiveNotification トップレベルに代替用の定数を用意して迂回すればエラーは回避できるっぽいですね
Avatar
ありがとうございます。既存コードに手を入れないで回避する方法はないですかね?(本当のproductionコードだと変更範囲がだいぶ広くなるなと思いまして)😅 (edited)
Avatar
Avatar
shiz
ありがとうございます。既存コードに手を入れないで回避する方法はないですかね?(本当のproductionコードだと変更範囲がだいぶ広くなるなと思いまして)😅 (edited)
ちょっと分からないですね😂 引数の方はともかくUIApplication.willResignActiveNotification はObjCからSwiftへのマッピング機能も何か影響していそうですが…
Avatar
Avatar
nanasi
ちょっと分からないですね😂 引数の方はともかくUIApplication.willResignActiveNotification はObjCからSwiftへのマッピング機能も何か影響していそうですが…
いえいえ、ありがとうございます!定数使うというのも一つの手段として検討してみます💡
Avatar
Avatar
koher
waiwaiの途中だけど・・・ さっきの Publisher の購読、 extension なしだとこれでいける気がする。 override func viewDidLoad() { super.viewDidLoad() let task = Task { [weak self] in guard let state = self?.state else { return } for await _ in state.objectWillChange.values { guard let self = self else { return } // state を View に反映する処理 self.nameLabel.text = state.user?.name } } cancellables.insert(.init { task.cancel() }) } (edited)
これ、 will なので state.objectWillChange.receive(on: DispatchQueue.main).values にするなどしないと更新された値が取れませんでした。
Avatar
omochimetaru 1/21/2022 3:48 AM
Hello, Swift Community. The review of SE-0339: Module Aliasing for Disambiguation, begins now and runs through January 31st, 2022. 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 emai...
3:48 AM
モジュール名の別名を付ける提案の審査してる
3:49 AM
言語機能じゃなくて、SwiftPM側で、あるターゲットがある依存を取り込む時にビルド設定として別名に置換するらしい
Avatar
com.apple.Foundation
Avatar
omochimetaru 1/21/2022 3:50 AM
ライブラリの中のターゲットで Logging みたいな名前が付いてると 別の Logging とぶつかる問題。
3:51 AM
Contains common infrastructural code for both SwiftPM and llbuild. - swift-tools-support-core/Package.swift at main · apple/swift-tools-support-core
3:51 AM
.target( /** TSCBasic support library */ name: "TSCBasic", dependencies: [ "TSCLibc", "TSCclibc", .product(name: "SystemPackage", package: "swift-system"), ], exclude: CMakeFiles + ["README.md"]),
3:51 AM
この問題があるから、 swift-tools-support-core とかは内部ターゲットに TSC prefix を付けるなどしている
Avatar
なるほど
Avatar
omochimetaru 1/21/2022 3:52 AM
この提案によって、こういうプレフィックスを付けなくてもよくなるはず。 (edited)
Avatar
Kishikawa Katsumi 1/21/2022 6:20 AM
SwiftPMのProposalだけどフロントエンドに変更も入るらしいからフロントエンドにパラメータ渡したらSwiftPMでも使えたりするのかな。
6:20 AM
フロントエンドだけで解決するものでもないんだろうか。
Avatar
Avatar
Kishikawa Katsumi
SwiftPMのProposalだけどフロントエンドに変更も入るらしいからフロントエンドにパラメータ渡したらSwiftPMでも使えたりするのかな。
omochimetaru 1/21/2022 6:32 AM
Xcodeでも、ですか?
6:33 AM
SwiftPMの仕様が、フロントエンドへのオプションとして展開されるらしいので、できるかもしれない。 xcodebuild越しのパラメータ設定で十分に再現できるかはわからない
Avatar
Kishikawa Katsumi 1/21/2022 6:41 AM
あ、間違えてる。SwiftPM以外でも、と書きたかった。SwiftPM以外のパッケージマネージャや直接XCFrameworkを入れた場合でもできたらかなりいいなあと。
Avatar
結構難しそう
Avatar
Kishikawa Katsumi 1/21/2022 6:43 AM
なんと。難しそうですか。
Avatar
omochimetaru 1/21/2022 6:44 AM
https://github.com/apple/swift-evolution/blob/main/proposals/0339-module-aliasing-for-disambiguation.md#detailed-design アーキテクチャ的なところはDetailed Designのところに結構詳しく書いてありますよ
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0339-module-aliasing-for-disambiguation.md at main · apple/swift-evolution
Avatar
直感ですがビルド前に介入できるspmのライブラリと、ビルド成果物であるxcframeworkとでは難易度が違う印象です
Avatar
omochimetaru 1/21/2022 6:46 AM
そういう意味か。↑の記述だと、 Utils をビルドする時にまず GameUtils としてビルドする って書いてあるから、確かにprebuiltなものだと難しいかも
Avatar
Kishikawa Katsumi 1/21/2022 6:46 AM
読んだ感じだと頑張ってリネームするっていうことだからいけるんじゃないかなって。
6:47 AM
マングルされたシンボル名とかも大変そうだけど動的に決まるような要素はないんじゃないかと思って。
Avatar
omochimetaru 1/21/2022 6:48 AM
First, we need to take the Utils module from swift-game and rename it GameUtils.
6:49 AM
あ、take from して rename か。
Avatar
func f(_: some Collection) { } の実装キタ https://github.com/apple/swift/pull/40993
Implement function parameters of the form some P be synthesizing an implicit generic parameter whose requirements come from the opaque type. We then map the opaque type back to the generic paramete...
Avatar
ウオオ
4:30 AM
ORTはまだ本物のreverse genericsにはならない…?
Avatar
そっちはまだですねぇ
Avatar
どっちかというとそっちのがほしいw
4:34 AM
シンプルに出来ることが増えるからね
Avatar
わかる
Avatar
昔は Opaque Argument Type って呼んでたはずなのに、いつからか Opaque Argument Type ってタームが消え去って、この PR だと Opaque Parameter になってるな。元々 "Improving the UI of generics" にあったはずなんだけど、編集されて残ってない。 ✏️ ボタンから編集履歴見ようとしたけど、クリックしても何も出てこない。見れないんだっけ? (edited)
Avatar
omochimetaru 1/25/2022 6:02 AM
argumentは呼び出しに与えるやつで関数の宣言に書く方はparameterだからその呼び替えは良さそう。
Avatar
aimai (SwiftUI-beginner) 1/30/2022 11:14 AM
質問チャンネルがここじゃなかったら言ってください!
Avatar
#beginner-help-archived がありますよ
Avatar
aimai (SwiftUI-beginner) 1/30/2022 11:26 AM
ごめんなさい
11:26 AM
ありがとうございます!
🤗 1
Avatar
omochimetaru 1/31/2022 3:30 AM
Hello Swift Community, TL;DR Swift has various reflection mechanisms, but they’re fragmented. By combining them, a more flexible and efficient reflection system could be established, that could enable features like compiler-synthesized conformances. ⚠ This post simply aims to start a discussion about the future of reflection and cultivate ide...
3:30 AM
動的なリフレクションのAPIを整えた上で、 Hashableの自動生成を、コンパイラ組み込みじゃなくてSwiftライブラリコードとして実装する提案
3:31 AM
その動的なリフレクションのコードは遅くなっちゃうけど、
3:31 AM
最適化によって、コンパイラ組み込み生成と同じものになるってアイデアが面白い。
Avatar
Kishikawa Katsumi 1/31/2022 3:34 AM
いいんじゃないか
Avatar
Tokamakで手書きしてる型リフレクション要らなくなると嬉しい
Avatar
omochimetaru 1/31/2022 3:42 AM
TokamakUIがまさに再発明してて大変な例として言及されてるね
👀 1
Avatar
きっとSwiftUIの実装も楽になるだろうから、アップル的にも嬉しい
Avatar
SwiftUIのリフレクションがSwiftに登ってくる説 (edited)
Avatar
omochimetaru 1/31/2022 3:45 AM
SwiftUIってそのへんもほんと変な作りだよなw
3:46 AM
普通は言語機能のリフレクションを先に整えそうだけど
3:46 AM
ABIが安定化してるからそれがなくても作れるっていう。 (edited)
Avatar
omochimetaru 2/2/2022 2:52 AM
Over the past few years there has been a huge amount of interest in bidirectional interoperability between Swift and C++. Thanks to the hard work of zoecarver, egor.zhdan, gribozavr, Michael Forster, Marcel Hlopko, scentini, and many other contributors, the Swift compiler is now able to import and use some C++ APIs, including C++ standard librar...
👀 1
2:53 AM
C++ Interopの実装が進んで、 std::vector とか使えるようになったらしい。 これからはC++ Interop Working Groupを作って、毎週ビデオ会議をやったりして進めていくらしい。
😊 1
Avatar
Kishikawa Katsumi 2/2/2022 2:56 AM
すごいね。ついにここまできたかって感じ。
Avatar
omochimetaru 2/2/2022 3:05 AM
すごい。
3:05 AM
Bridging Generic APIs In this post I'm going to lay out how I propose we bridge generic C++ APIs to Swift. Refresher If you’re already familiar with both Swift generics and C++ templates, feel free to skim this section and move on to "Goals." C++ Templates In C++ templates can be used for generic programming. Templates, as their name suggest...
3:05 AM
早速、C++ TemplatesがSwiftにインポートさせたときにうまく言語仕様と噛み合わせられなくて困ったよ、ってトピックも投稿されてる。
Avatar
These are not too far away from C macros, but are substantially more ~complicated~ powerful.
3:12 AM
Avatar
omochimetaru 2/2/2022 3:23 AM
何回か読み直したけど論点がよくわからない・・・
3:25 AM
Class Templatesの章に書いてる func generic<T>(_ v: std.vector<T>)func concrete(_ v: std.vector<CInt>) の両方に、 let vec = std.vector<CInt>() を渡せるモデルって、今のSwiftの型でいけるよね?
Avatar
2回読み直したけどわかんなかった
3:52 AM
In the above example, depending on the call, vec needs to be both abstract and concrete.
Avatar
omochimetaru 2/14/2022 5:47 AM
可変長ジェネリックパラメータのランタイムABIについて検討するスレッドが立ってた https://forums.swift.org/t/abi-for-variadic-generics/55213 言語仕様のスレッドはこっち https://forums.swift.org/t/variadic-generics/54511
The language design for variadic generics is well underway, and it's time to start settling on decisions about how we're going to implement it. We can roughly divide the implementation into eight pieces: parsing representation in the AST type-checking representation in SIL AST-to-SIL lowering SIL analyses and optimizations SIL-to-LLVM lowerin...
Hello Swift Evolution, I'm pleased to bring you a refined copy of the variadic generics proposal, which was first pitched in this thread. The proposal text is available inline and online. I look forward to your feedback and questions. Variadic Generics Proposal: SE-NNNN Authors: Robert Widmann Review Manager: TBD Status: Awaiting implem...
Avatar
omochimetaru 2/16/2022 5:55 AM
Hello, Swift community. The third review of SE-0329: Clock, Instant, and Duration has come to an end. This review was narrowly focused on some APIs involving the Duration type; other aspects of the proposal were accepted during prior reviews. Review feedback was much lighter, which is not surprising given the narrow scope of the review. The ...
5:55 AM
時間関係の型を追加する提案が採択されたので、プロポーザルを読み直していたんですが気になる箇所があって
5:56 AM
ContinuousClockのところに
On Darwin platforms this refers to time derived from the monotonic clock, for linux platforms this is in reference to the uptime clock; being that those two are the closest in behavioral meaning.
と書いてあって
5:56 AM
SuspendingClockのところに
For Darwin based platforms this is derived from the uptime clock whereas for linux based platforms this is derived from the monotonic clock since those most closely represent the concept for not incrementing while the machine is asleep.
5:56 AM
と書いてあって、
5:57 AM
Continuous: Darwin -> monotonic clock; Linux -> uptime Suspending: Darwin -> uptime; Linux -> monotonic clock
5:57 AM
uptimeを使うかmonotonic clockを使うかが、macとlinuxで反転しているんですけど
5:58 AM
詳しく知りたいんですが、このあたり詳しくなくて、何を見たらいいやら。
Avatar
単なるミスという可能性
Avatar
omochimetaru 2/16/2022 5:59 AM
あと、僕が英語を読み違えてる?説もある (edited)
Avatar
"concept for not incrementing while the machine is asleep" がXNUとLinuxで違う...?
Avatar
だとしたら面白い
Avatar
omochimetaru 2/16/2022 6:01 AM
このあたりですね、確かに逆転している
6:01 AM
正確には continuous linux: CLOCK_BOOTTIME continuous mac: CLOCK_MONOTONIC suspending linux: CLOCK_MONOTONIC_RAW suspending mac: CLOCK_UPTIME_RAW (edited)
6:02 AM
で、4ケースとも別の時計を取ってるな
Avatar
clock_gettime(3) からのそれぞれの実装みればわかるのではないかな...
Avatar
omochimetaru 2/16/2022 6:03 AM
なるほど
6:04 AM
6:05 AM
CLOCK_BOOTTIME は mac にはそもそも無いんだな
6:05 AM
6:06 AM
BLOCK_BOOTTIME は Linux 2.6.39 で追加されたらしい
Avatar
なるほど
6:07 AM
uptimeという表現がconfusingってことですねえ (edited)
Avatar
omochimetaru 2/16/2022 6:07 AM
たしかに、Linuxのマニュアルだと、 CLOCK_BOOTTIME はスリープ中も増加するけど、CLOCK_MONOTONICはそうではない(停止する) と書いてあって
Avatar
面白い
Avatar
omochimetaru 2/16/2022 6:07 AM
macのマニュアルだと、 CLOCK_MONOTONIC がスリープ中も増加するって書いてある
Avatar
POSIXじゃないのかなこれらは。
Avatar
omochimetaru 2/16/2022 6:08 AM
STANDARDS The clock_gettime(), clock_settime(), and clock_getres() system calls conform to IEEE Std 1003.1b-1993 (``POSIX.1''). cleck_gettime_nsec_np() is a non-portable Darwin extension. The clock IDs CLOCK_MONOTONIC_RAW and CLOCK_UPTIME_RAW are extensions to the POSIX interface.
6:09 AM
もしかしてposixには「スリープ」の概念が無いのかな?
Avatar
POSIX準拠(POSIXに準拠するとは言ってない) (edited)
6:09 AM
(XNUあるある)
Avatar
omochimetaru 2/16/2022 6:10 AM
難しいな〜 これは標準ライブラリで隠蔽してもらえると嬉しいやつだ
Avatar
omochimetaru 2/18/2022 2:38 AM
Hi all, I've been looking into generics ergonomics, and one of the problems that keeps coming up is that going from concrete types or generics into existentials is a bit of a one-way street: you can create an any P from a value of any type that conforms to P, but once you have that existential value of type any P it's hard to get back to using ...
2:38 AM
existentialを暗黙にopenする、とんでもない仕様の提案が出てる
2:39 AM
見かけ上 any P が P に準拠するようになる
Avatar
_openExistential あるしprotocol extensionでもopenできるし、裏技だったやつが表に出てきた?
Avatar
omochimetaru 2/18/2022 2:41 AM
そうそう。
2:42 AM
裏技の経由を不要にする (edited)
Avatar
裏技w
Avatar
_openExistential 初めて知った
Avatar
omochimetaru 2/18/2022 2:43 AM
_openExistential のインターフェースは Swift言語で 型を記述できないマジック関数
Avatar
omochimetaru 2/18/2022 2:54 AM
protocol Costume { func withBells() -> Self func hasSameAdornments(as other: Self) -> Bool } func hasBells<C: Costume>(_ costume: Costume) -> Bool { return costume.hasSameAdornments(as: costume.withBells()) }
2:54 AM
func checkFinaleReadiness(costumes: [any Costume]) -> Bool { for costume in costumes { if !hasBells(costume) { // okay with this proposal: C is bound to the type stored inside the 'any' box, known only at runtime return false } } return true } ↑これができるようになる
2:56 AM
func checkFinaleReadinessOpenCoded(costumes: [any Costume]) -> Bool { for costume: some Costume in costumes { // implicit generic parameter binds to underlying type of each costume let costumeWithBells = costume.withBells() // returned type is the same 'some Costume' as 'costume' if !costume.hasSameAdornments(costumeWithBells) { // okay, 'costume' and 'costumeWithBells' have the same type return false } } return true } ↑これもできるようにするって書いてあるのかな・・・?
2:57 AM
any P に対して Self を返すメソッドを呼び出すと、 some P として返ってくる
2:59 AM
func cannotOpen1<T: P>(_ array: [T]) { .. } func cannotOpen2<T: P>(_ a: T, _ b: T) { ... } func cannotOpen3<T: P>(_ values: T...) { ... } struct X<T> { } func cannotOpen4<T: P>(_ x: X<T>) { } func cannotOpen5<T: P>(_ x: T, _ a: T.A) { } func cannotOpen6<T: P>(_ x: T?) { } func testCannotOpenMultiple(array: [any P], p1: any P, p2: any P, xp: X<any P>, pOpt: (any P)?) { cannotOpen1(array) // each element in the array can have a different underlying type, so we cannot open cannotOpen2(p1, p2) // p1 and p2 can have different underlying types, so there is no consistent binding for 'T' cannotOpen3(p1, p2) // similar to the case above, p1 and p2 have different types, so we cannot open them cannotOpen4(xp) // cannot open the existential in 'X<any P>' there isn't a specific value there. cannotOpen5(p1, p2.getA()) // cannot open either argument because 'T' is used in both parameters cannotOpen6(pOpt) // cannot open the existential in '(any P)?' because it might be nil, so there would not be an underlying type } ↑ structural position だと P のオブジェクトの数が動的になるから open できない
Avatar
一瞬ウェッと思ったけど、直感は成り立つンじゃないかと言っている
Avatar
omochimetaru 2/18/2022 3:02 AM
Optionalのケースがだめなのは面白いな。実際の (any P)?nil のときに、動的な真の型が取り出せない (edited)
3:02 AM
Neverがボトムタイプだったら、そのときは Never: P として open できそうだけど
Avatar
X<any P> がダメだしそれはそう
3:06 AM
as? 的に失敗を許容するバリアントが欲しくなる?
Avatar
omochimetaru 2/18/2022 3:06 AM
厳密には X<any P> については X<T>T を返すメソッドを持ってるかどうかじゃないかな
Avatar
Tを引数にとる場合とTを返す場合があって (edited)
3:08 AM
swiftのgenericsはそれを区別する型でないから、出来るかどうかが型として明示的にならないと思う
Avatar
返り値の型に出現するかどうかはチェックできるんじゃないですかね。頑張れば
Avatar
Avatar
tarunon
swiftのgenericsはそれを区別する型でないから、出来るかどうかが型として明示的にならないと思う
omochimetaru 2/18/2022 3:11 AM
正しいと思う。
3:11 AM
多分同じことを言っていて
3:12 AM
今の Swift のジェネリック型のパラメータ部分は保守的に invariant だから、その規則だと無理ってことになるけど
3:12 AM
メンバ単位で出現状況をチェックするようにしたら、許容しうるという話
Avatar
X<in T> X<out T> X<inout T> が表現できるようになれば
Avatar
omochimetaru 2/18/2022 3:13 AM
で、 Optional型に絞って考えれば、コンパイラ特別扱いで、 out parameter なのは既知だからありじゃないかってのが俺の言った事
Avatar
許される境界を作れる
Avatar
omochimetaru 2/18/2022 3:13 AM
現在でも T < U で T? < U? の暗黙変換があるのは Optional の T が out parameter という知識が組み込まれてるからなので。
3:14 AM
ただ Never: P も現状は実装されてないから飛躍が2つ必要。
Avatar
なるほど
Avatar
このPRがマージされて、いつものようにWasmビルドが壊れたので直してたんですが、WASIはsleep中のクロックの増加に対して何も規定していなくて困ったな〜となった。が、ふとWindows向けの実装を見てみると ContinuousClockSuspendingClock で全く同じ実装になってたので、WASIもそんな感じでお茶を濁しました。(それでいいのか?) https://github.com/apple/swift/blob/a0fbce0ffd111243bef190b58f838c269dfc5efd/stdlib/public/Concurrency/Clock.cpp#L74-L86 https://github.com/apple/swift/blob/a0fbce0ffd111243bef190b58f838c269dfc5efd/stdlib/public/Concurrency/Clock.cpp#L46-L57 (edited)
Avatar
Avatar
Yuta Saito
このPRがマージされて、いつものようにWasmビルドが壊れたので直してたんですが、WASIはsleep中のクロックの増加に対して何も規定していなくて困ったな〜となった。が、ふとWindows向けの実装を見てみると ContinuousClockSuspendingClock で全く同じ実装になってたので、WASIもそんな感じでお茶を濁しました。(それでいいのか?) https://github.com/apple/swift/blob/a0fbce0ffd111243bef190b58f838c269dfc5efd/stdlib/public/Concurrency/Clock.cpp#L74-L86 https://github.com/apple/swift/blob/a0fbce0ffd111243bef190b58f838c269dfc5efd/stdlib/public/Concurrency/Clock.cpp#L46-L57 (edited)
Windowsはどうなんだろうなこれw WASIに関しては、Sleepの概念が存在してるかも微妙だね
Avatar
なんとpollのタイムアウトでsleepを表現します
Avatar
omochimetaru 2/18/2022 1:32 PM
あ、待ちじゃなくて、OSのスリープ状態のことね
Avatar
omochimetaru 2/22/2022 3:40 AM
I'm excited to see this, opening existentials is a major gap in Swift expressiveness. I'm a bit concerned about the need to repeat the protocol name in some P. It does not look that bad in proposal with single-letter names, but I'm afraid that in production code it may be pretty verbose: func authenticate(alternativeAuthenticationProviders: [...
3:41 AM
protocol P { static func make() -> Self {} } func f<T: P>(x: T?) { print(x ?? T.make()) } let x: (any P)? = nil f(x) // It is not valid to substitute [T = Never] here
3:42 AM
Neverは 全てのexistential には代入できるけど 全てのprotocolには代入できないという意見をもらった
3:42 AM
↑たしかに上記コードだと Never.make() -> Never を呼び出す事になって実行時エラーが生じる
3:43 AM
実行時エラーが生じる事と、Neverが bottom type であるかどうかはまた別な気もするけど fatalError 関数とか実在するし
Avatar
Neverが値として出現するならばそれはクラッシュなんじゃないか
3:46 AM
だから実行時エラーになる、というのはむしろそうなるべきであるはず
Avatar
omochimetaru 2/22/2022 3:47 AM
実行時エラーでそこで止まる分には、型理論的には壊れてない、よねえ?
3:48 AM
うーんでもそれ言うとなんでもありになっちゃうか?
Avatar
それが正しいと思います
3:48 AM
Neverはそもそもそういう型だと思いますよ
Avatar
omochimetaru 2/22/2022 3:48 AM
クラッシュすれば見逃されるんなら、 どんな型もどんな型に代入できる
Avatar
BottomTypeはそういうものであるべき
Avatar
omochimetaru 2/22/2022 3:48 AM
ああNeverだけがその無茶苦茶な互換性を認められたものってことか
Avatar
発生しない値だから、何にでもなれる
Avatar
ここで言ってるのは
but it does not conform to every protocol:
だからNever: Pが常に成り立つとは限らないという話?
Avatar
omochimetaru 2/22/2022 3:55 AM
でもその例としての P.make は、 Self = Never を返す関数として、クラッシュしたらいいから、成り立たせられる (edited)
Avatar
Pのstaticメソッドに返り値がSelfじゃないものがあると成り立たなくなる? (edited)
Avatar
omochimetaru 2/22/2022 3:56 AM
例えば make の返り値が Int 固定だったら埋めようが無いから駄目か? (edited)
Avatar
protocol P { static func foo() -> Int } extension Never: P { static func foo() -> Int { ??? } } func takeP<T: P>(x: T) -> Int { T.foo() } let x: (any P)? = nil takeP(x) (edited)
3:57 AM
そうそう
Avatar
そもそも前提としてNeverの実体化が出来ないのだから
3:57 AM
その関数が実行されることはなく問題にならない
Avatar
Never.Typeは実体化出来る
Avatar
あ〜
3:57 AM
なるほど
Avatar
Avatar
tarunon
そもそも前提としてNeverの実体化が出来ないのだから
omochimetaru 2/22/2022 3:57 AM
インスタンスは存在しないけど、metatypeは居るんだよな
3:58 AM
static funcに関してはnever特権理論が消えるのかなあ。
Avatar
Never.Typeに対する関数呼び出しをクラッシュにしてしまって
3:58 AM
解決ということにした方が、諸々シンプルになる気がするなぁ
Avatar
omochimetaru 2/22/2022 3:59 AM
でもそれだと、 あらゆる P の static func が
3:59 AM
Neverいれて実行時エラーを生じさせる事にもなるね (edited)
Avatar
(any P)?のopenを禁止して、ちゃんとユーザにオプショナルアンラップさせるほうが良い気がするなぁ
Avatar
他の言語のprotocol相当の機能にstatic関数がついてない事が多い理由が、ここにある気がしてきた (edited)
Avatar
Avatar
tarunon
他の言語のprotocol相当の機能にstatic関数がついてない事が多い理由が、ここにある気がしてきた (edited)
omochimetaru 2/22/2022 4:00 AM
static func or associatedtype があったらNever conformはできない、というのはありかも。
4:00 AM
PATと同じ条件
Avatar
それもいいかもね
Avatar
omochimetaru 2/22/2022 4:01 AM
言い換えると、他の言語だとnon PATしかないんだよね。 (edited)
Avatar
Neverはstatic関数ある場合は自動でconformしない(ユーザがextensionする分にはok)
4:01 AM
これは良いバランスだと思う
Avatar
Avatar
tarunon
Neverはstatic関数ある場合は自動でconformしない(ユーザがextensionする分にはok)
omochimetaru 2/22/2022 4:02 AM
よさそう
Avatar
ユーザが書くと関数の実装も強制される
Avatar
そうか、ユーザが勝手にconformance実装できるから、自動実装と思えば自然か
Avatar
initは良いんだっけ
Avatar
-> Selfまたは-> Self?だから良い?
Avatar
throwsと将来的にasyncもあるけど (edited)
4:04 AM
うーんグレーだな、落として良い気がする
Avatar
omochimetaru 2/22/2022 4:04 AM
-> SelffatalError() と同じで実装しないままクラッシュで許すはありな気もする (edited)
Avatar
omochimetaru 3/3/2022 8:15 AM
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) test2 { // com.apple.root.default-qos.cooperative print(Thread.current) } test2 { @MainActor () in // com.apple.main-thread print(Thread.current) } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) }
8:16 AM
無印関数を @MainActor 関数に変換するときに、メインスレッドにホップするサンクでラップしてくれないの、おかしそう
Avatar
@swift-5.5.3 -Xfrontend -parse-as-library import Foundation @main struct Entrypoint { static func main() async throws { let _: () = await withUnsafeContinuation { c in test2 { // com.apple.root.default-qos.cooperative print(Thread.current) c.resume(returning: ()) } } let _: () = await withUnsafeContinuation { c in test2 { @MainActor () in // com.apple.main-thread print(Thread.current) c.resume(returning: ()) } } } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) } (edited)
Avatar
Avatar
Yuta Saito
@swift-5.5.3 -Xfrontend -parse-as-library import Foundation @main struct Entrypoint { static func main() async throws { let _: () = await withUnsafeContinuation { c in test2 { // com.apple.root.default-qos.cooperative print(Thread.current) c.resume(returning: ()) } } let _: () = await withUnsafeContinuation { c in test2 { @MainActor () in // com.apple.main-thread print(Thread.current) c.resume(returning: ()) } } } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) } (edited)
<Thread: 0x00007f0e14001040> <Thread: 0x00007f0e14001040> (edited)
Avatar
なんか余計なもんつけちゃった?
Avatar
omochimetaru 3/3/2022 10:56 AM
queueの名前はデバッガで止めて調べました、実はこのprintでは出ないです
10:56 AM
あれ、スレッドが同じだな
10:57 AM
static func main() って 暗黙のMainActor ? (edited)
Avatar
いやー、めっちゃありそうなバグなんですよね。Actorホッピング漏れ結構ある
10:58 AM
普通にViewControllerにペタっと貼っても再現しなかったです
Avatar
omochimetaru 3/3/2022 10:58 AM
実験してるコードだと、 viewDidAppear とは書いてあるけど、これVCじゃなくて、全く @MainActor じゃないクラスです
Avatar
ふむふむ
Avatar
omochimetaru 3/3/2022 10:58 AM
ViewControllerとかさっきのstaticfuncmainだと
10:59 AM
メソッドが @MainActor なせいで、クロージャリテラルも @MainActor に推論されてないかね
Avatar
あ、このviewDidAppearめっちゃUIViewControllerっぽかったけどそうじゃなかったんですねw
Avatar
@swift-5.5.3 -Xfrontend -parse-as-library import Foundation @globalActor actor OtherActor { static let shared = OtherActor() static func run(_ body: @OtherActor () async -> Void) async { @OtherActor func inner() async { await body() } await inner() } } @main struct Entrypoint { static func main() async throws { await OtherActor.run { let _: () = await withUnsafeContinuation { c in test2 { // com.apple.root.default-qos.cooperative print(Thread.current) c.resume(returning: ()) } } let _: () = await withUnsafeContinuation { c in test2 { @MainActor () in // com.apple.main-thread print(Thread.current) c.resume(returning: ()) } } } } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) } (edited)
Avatar
Avatar
Yuta Saito
@swift-5.5.3 -Xfrontend -parse-as-library import Foundation @globalActor actor OtherActor { static let shared = OtherActor() static func run(_ body: @OtherActor () async -> Void) async { @OtherActor func inner() async { await body() } await inner() } } @main struct Entrypoint { static func main() async throws { await OtherActor.run { let _: () = await withUnsafeContinuation { c in test2 { // com.apple.root.default-qos.cooperative print(Thread.current) c.resume(returning: ()) } } let _: () = await withUnsafeContinuation { c in test2 { @MainActor () in // com.apple.main-thread print(Thread.current) c.resume(returning: ()) } } } } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) } (edited)
<Thread: 0x00007f8c100030f0> <Thread: 0x00007f8bec000c20> (edited)
Avatar
ほい
Avatar
ここでparse-as-libraryつけるのってどんな意味があるんですか
Avatar
無いと@main書けないので付けてますね
t_naruhodo 1
Avatar
omochimetaru 3/3/2022 11:05 AM
[omochi@omochi-iMacPro async]$ swift -Xfrontend -parse-as-library a.swift JIT session error: Symbols not found: [ _swift_task_asyncMainDrainQueue, _swift_task_getMainExecutor ] Failed to materialize symbols: { (main, { _symbolic B0, _$s1a4MainVN, _$sIetH_yts5Error_pIegHrzo_TRTu, _$sS2cMScAsWl, _symbolic IetH_, _$s1a4TestCMa, _$s1aMXM, ___swift_async_resume_project_context, _$s1a4MainV4mainyyYaKFZTu, _$s1a4MainVMn, __swift_async_extendedFramePointerFlagsUser, _$s1a4MainVMa, _$s1a4TestC5test2yyyyYacFTq, _$s1a4TestC5test1yyyyYaScMYccF, _symbolic _____ 1a4MainV, _$s1a4TestC5test2yyyyYacF, _$s1a4TestC5test1yyyyYaScMYccFTq, _$s1a4TestCMm, _$s1a4MainV5$mainyyYaKFZ, _symbolic IegH_, _$s1a4TestCN, _$sSccySccyxq_GBccfC, _$sScTss5NeverORs_rlE8detached8priority9operationScTyxABGScPSg_xyYaYbcntFZ, $.a.__inits.0, __swift_FORCE_LOAD_$_swiftObjectiveC_$_a, _$sScPSgMD, _$s1a4TestCACycfCTq, _$s1a4TestC4mainyyYaFTq, _$sIetH_yts5Error_pIegHrzo_TR, _$sIeghH_ytIeghHr_TRTu, _$s1a4TestCfd, _$sSa12_endMutationyyF, _$s1a4TestCACycfC, _$sScPSgWOh, _main, _$sIeghH_ytIeghHr_TR, _$sScPSgWOc, _async_MainTu, _async_Main, _symbolic IeghH_, _$s1a4MainV4mainyyYaKFZ, _$s1a4TestCACycfc, __swift_FORCE_LOAD_$_swiftCoreGraphics_$_a, _got.$sSccMn, ___swift_async_resume_get_context, _$sxIeghHr_xs5Error_pIegHrzo_s5NeverORs_r0_lTR, _got.$ss5NeverOMn, _$sScTyScTyxq_GBocfC, _$ss27_finalizeUninitializedArrayySayxGABnlF, _got.$sScPMn, _$sS2cMScAsWL, ___swift_instantiateConcreteTypeFromMangledName, _$s1a4TestCfD, _$ss22withUnsafeContinuationyxySccyxs5NeverOGXEYalFyBcXEfU_, _symbolic _____Sg ScP, _$ss22withUnsafeContinuationyxySccyxs5NeverOGXEYalF, __swift_FORCE_LOAD_$_swiftDarwin_$_a, _$s1a4TestCMn, _symbolic xIeghHr_, _$s1a4TestC4mainyyYaFTu, __swift_FORCE_LOAD_$_swiftCoreFoundation_$_a, _$ss5print_9separator10terminatoryypd_S2StFfA1_, _symbolic _____ 1a4TestC, _$sScc6resume9returningyxn_ts5NeverORs_rlF, _$s1a4TestC4mainyyYaF, __swift_FORCE_LOAD_$_swiftDispatch_$_a, _$sxIeghHr_xs5Error_pIegHrzo_s5NeverORs_r0_lTRTu, _$ss5print_9separator10terminatoryypd_S2StFfA0_, _symbolic _____yyt_____G Scc s5NeverO, __swift_FORCE_LOAD_$_swiftXPC_$_a, _$s1a4MainV5$mainyyYaKFZTu, _symbolic x, __swift_FORCE_LOAD_$_swiftFoundation_$_a, __swift_FORCE_LOAD_$_swiftIOKit_$_a, _$ss22withUnsafeContinuationyxySccyxs5NeverOGXEYalFTu }) }
11:05 AM
あー BigSurだからか
Avatar
Immediateモードやめよう
Avatar
Avatar
swift55
<Thread: 0x00007f8c100030f0> <Thread: 0x00007f8bec000c20> (edited)
omochimetaru 3/3/2022 11:06 AM
別のスレッドになった?
Avatar
なってますねー
Avatar
@swift-5.5.3 -Xfrontend -parse-as-library import Foundation @globalActor actor OtherActor { static let shared = OtherActor() static func run(_ body: @OtherActor () async -> Void) async { @OtherActor func inner() async { await body() } await inner() } } @main struct Entrypoint { static func main() async throws { print(Thread.current, Thread.isMainThread) await OtherActor.run { let _: () = await withUnsafeContinuation { c in test2 { // com.apple.root.default-qos.cooperative print(Thread.current, Thread.isMainThread) c.resume(returning: ()) } } let _: () = await withUnsafeContinuation { c in test2 { @MainActor () in // com.apple.main-thread print(Thread.current, Thread.isMainThread) c.resume(returning: ()) } } } } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) } (edited)
Avatar
Avatar
Iceman
@swift-5.5.3 -Xfrontend -parse-as-library import Foundation @globalActor actor OtherActor { static let shared = OtherActor() static func run(_ body: @OtherActor () async -> Void) async { @OtherActor func inner() async { await body() } await inner() } } @main struct Entrypoint { static func main() async throws { print(Thread.current, Thread.isMainThread) await OtherActor.run { let _: () = await withUnsafeContinuation { c in test2 { // com.apple.root.default-qos.cooperative print(Thread.current, Thread.isMainThread) c.resume(returning: ()) } } let _: () = await withUnsafeContinuation { c in test2 { @MainActor () in // com.apple.main-thread print(Thread.current, Thread.isMainThread) c.resume(returning: ()) } } } } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) } (edited)
<Thread: 0x000000000a1b43a0> true <Thread: 0x00007f1a64002d20> false <Thread: 0x00007f1a44000c40> false (edited)
Avatar
あれ、main()はMainActorのスレッドというわけではないのか
Avatar
omochimetaru 3/3/2022 11:08 AM
class Test { func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } func test2(_ f: @escaping () async -> Void) { test1(f) } func main() async { let _: Void = await withUnsafeContinuation { c in test2 { print(Thread.current) c.resume(returning: ()) } } let _: Void = await withUnsafeContinuation { c in test2 { @MainActor () in print(Thread.current) c.resume(returning: ()) } } } } // AppDelegate func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { Task.detached { await Test().main() } return true } (edited)
Avatar
いや、MainActor強制です
Avatar
omochimetaru 3/3/2022 11:08 AM
iOSのappDelegateにコピペしたら再現できるようにした
11:09 AM
このとき出力が <NSThread: 0x282cdc480>{number = 5, name = (null)} <_NSMainThread: 0x282c8c080>{number = 1, name = main}
Avatar
むしろ後者のMainActorついたクロージャがメインスレッドじゃないとこで実行されてるのか
Avatar
omochimetaru 3/3/2022 11:10 AM
あれ?
Avatar
Avatar
swift55
<Thread: 0x000000000a1b43a0> true <Thread: 0x00007f1a64002d20> false <Thread: 0x00007f1a44000c40> false (edited)
omochimetaru 3/3/2022 11:11 AM
この結果はこっちの実験とはまた違うね。どっちもメインスレッドじゃないじゃん。
Avatar
detachedでキューにスケジューリングされて実行順入れ替わってる?
11:11 AM
ラベル付け無いとわからん
Avatar
omochimetaru 3/3/2022 11:11 AM
ああそうか
11:11 AM
test2はなげっぱで待機してないから実行とログの組み合わせが確定してない (edited)
Avatar
@swift-5.5.3 @swift-main -Xfrontend -parse-as-library import Foundation @globalActor actor OtherActor { static let shared = OtherActor() static func run(_ body: @OtherActor () async -> Void) async { @OtherActor func inner() async { await body() } await inner() } } @main struct Entrypoint { static func main() async throws { print(Thread.current, Thread.isMainThread) await OtherActor.run { let _: () = await withUnsafeContinuation { c in test2 { // com.apple.root.default-qos.cooperative print("t1", Thread.current, Thread.isMainThread) c.resume(returning: ()) } } let _: () = await withUnsafeContinuation { c in test2 { @MainActor () in // com.apple.main-thread print("t2", Thread.current, Thread.isMainThread) c.resume(returning: ()) } } } } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) } (edited)
Avatar
Avatar
Yuta Saito
@swift-5.5.3 @swift-main -Xfrontend -parse-as-library import Foundation @globalActor actor OtherActor { static let shared = OtherActor() static func run(_ body: @OtherActor () async -> Void) async { @OtherActor func inner() async { await body() } await inner() } } @main struct Entrypoint { static func main() async throws { print(Thread.current, Thread.isMainThread) await OtherActor.run { let _: () = await withUnsafeContinuation { c in test2 { // com.apple.root.default-qos.cooperative print("t1", Thread.current, Thread.isMainThread) c.resume(returning: ()) } } let _: () = await withUnsafeContinuation { c in test2 { @MainActor () in // com.apple.main-thread print("t2", Thread.current, Thread.isMainThread) c.resume(returning: ()) } } } } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) } (edited)
<Thread: 0x000000000b6fdf60> true t1 <Thread: 0x00007fa520002d40> false t2 <Thread: 0x00007fa508000c60> false (edited)
Avatar
Avatar
Yuta Saito
@swift-5.5.3 @swift-main -Xfrontend -parse-as-library import Foundation @globalActor actor OtherActor { static let shared = OtherActor() static func run(_ body: @OtherActor () async -> Void) async { @OtherActor func inner() async { await body() } await inner() } } @main struct Entrypoint { static func main() async throws { print(Thread.current, Thread.isMainThread) await OtherActor.run { let _: () = await withUnsafeContinuation { c in test2 { // com.apple.root.default-qos.cooperative print("t1", Thread.current, Thread.isMainThread) c.resume(returning: ()) } } let _: () = await withUnsafeContinuation { c in test2 { @MainActor () in // com.apple.main-thread print("t2", Thread.current, Thread.isMainThread) c.resume(returning: ()) } } } } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) } (edited)
swiftNightly BOT 3/3/2022 11:18 AM
<Thread: 0x000000000b244040> true t1 <Thread: 0x00007ff42c12ce70> false t2 <Thread: 0x00007ff414000c40> false
Avatar
クロージャにMainActorついてても呼び出す側の気分で変わるのかあ
Avatar
omochimetaru 3/3/2022 11:18 AM
それは余計に困る。
Avatar
ホップは基本的にcaller側の責務ですね
Avatar
omochimetaru 3/3/2022 11:19 AM
え、そうなの?
11:19 AM
それなら test1 の await f() で hop してないのが変ってことになるけど
Avatar
Avatar
omochimetaru 3/3/2022 11:20 AM
他にもいろいろ試した感じでは、callee側で、ラムダ式を書くときに
11:20 AM
自己hopな関数が生成されてると思った
Avatar
@swift-5.5.3 -Xfrontend -parse-as-library import Foundation @globalActor actor OtherActor { static let shared = OtherActor() static func run(_ body: @OtherActor () async -> Void) async { @OtherActor func inner() async { await body() } await inner() } } @main struct Entrypoint { static func main() async throws { print(Thread.current, Thread.isMainThread) await OtherActor.run { let _: () = await withUnsafeContinuation { c in test2 { // com.apple.root.default-qos.cooperative print("t1", Thread.current, Thread.isMainThread) c.resume(returning: ()) } } let _: () = await withUnsafeContinuation { c in test2 { @MainActor () in // com.apple.main-thread print("t2", Thread.current, Thread.isMainThread) assumeMainActor() c.resume(returning: ()) } } } } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) } @MainActor func assumeMainActor() { print("Here must be MainActor! but Thread.isMainThread = \(Thread.isMainThread)") }
Avatar
Avatar
Yuta Saito
@swift-5.5.3 -Xfrontend -parse-as-library import Foundation @globalActor actor OtherActor { static let shared = OtherActor() static func run(_ body: @OtherActor () async -> Void) async { @OtherActor func inner() async { await body() } await inner() } } @main struct Entrypoint { static func main() async throws { print(Thread.current, Thread.isMainThread) await OtherActor.run { let _: () = await withUnsafeContinuation { c in test2 { // com.apple.root.default-qos.cooperative print("t1", Thread.current, Thread.isMainThread) c.resume(returning: ()) } } let _: () = await withUnsafeContinuation { c in test2 { @MainActor () in // com.apple.main-thread print("t2", Thread.current, Thread.isMainThread) assumeMainActor() c.resume(returning: ()) } } } } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) } @MainActor func assumeMainActor() { print("Here must be MainActor! but Thread.isMainThread = \(Thread.isMainThread)") }
<Thread: 0x000000000ad55e70> true t1 <Thread: 0x00007f1f68002d40> false t2 <Thread: 0x00007f1f48000c60> false Here must be MainActor! but Thread.isMainThread = false
Avatar
assumeMainActorのcallerはMainActorに居ると信じているので、assumeMainActor呼ぶ前にhopしなくて、こういうことになります。
Avatar
omochimetaru 3/3/2022 11:24 AM
@swift-5.5.3 -Xfrontend -parse-as-library import Foundation @globalActor actor OtherActor { static let shared = OtherActor() static func run(_ body: @OtherActor () async -> Void) async { @OtherActor func inner() async { await body() } await inner() } } @main struct Entrypoint { static func main() async throws { print(Thread.current, Thread.isMainThread) await OtherActor.run { let _: () = await withUnsafeContinuation { c in test1 { print("t1", Thread.current, Thread.isMainThread) c.resume(returning: ()) } } let _: () = await withUnsafeContinuation { c in test1 { @MainActor () in print("t2", Thread.current, Thread.isMainThread) assumeMainActor() c.resume(returning: ()) } } } } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) } @MainActor func assumeMainActor() { print("Here must be MainActor! but Thread.isMainThread = \(Thread.isMainThread)") }
Avatar
Avatar
omochimetaru
@swift-5.5.3 -Xfrontend -parse-as-library import Foundation @globalActor actor OtherActor { static let shared = OtherActor() static func run(_ body: @OtherActor () async -> Void) async { @OtherActor func inner() async { await body() } await inner() } } @main struct Entrypoint { static func main() async throws { print(Thread.current, Thread.isMainThread) await OtherActor.run { let _: () = await withUnsafeContinuation { c in test1 { print("t1", Thread.current, Thread.isMainThread) c.resume(returning: ()) } } let _: () = await withUnsafeContinuation { c in test1 { @MainActor () in print("t2", Thread.current, Thread.isMainThread) assumeMainActor() c.resume(returning: ()) } } } } } private func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } private func test2(_ f: @escaping () async -> Void) { test1(f) } @MainActor func assumeMainActor() { print("Here must be MainActor! but Thread.isMainThread = \(Thread.isMainThread)") }
<Thread: 0x000000000a88e080> true t1 <Thread: 0x00007f28a0000c60> false t2 <Thread: 0x00007f28a0000c60> false Here must be MainActor! but Thread.isMainThread = false
Avatar
omochimetaru 3/3/2022 11:24 AM
むむっ
11:25 AM
test2じゃなくてtest1を直接呼ぶように変えたら
11:25 AM
t1もt2も、メインスレッドじゃないのはおかしいんだけど、でも、同じスレッドになった。
11:25 AM
test2を呼ぶテストのときは、t1とt2が、別のスレッドになったのに。
Avatar
なんじゃこりゃ
Avatar
偶然?
Avatar
omochimetaru 3/3/2022 11:27 AM
手元での実験だとクロージャ自体がメインに投入するようになってるからこそ、片方は変なスレッドだけど、もう片方はメインスレッドになった と解釈してたけど
11:28 AM
ここのLinuxの実験だと、まったく違う結果というか、何をどうやってもメインに投入されてないので
Avatar
Task.detachedは実行時にActorを継承しないけど、なぜか静的にはクロージャの中がMainActorに居ることになっていて、f()でホップが発生してない。
Avatar
omochimetaru 3/3/2022 11:28 AM
お話にならないように見える
11:29 AM
あー、Task.detachedを書く場所の違い?
11:30 AM
グローバル関数なのか、クラスのメソッドなのかで、
11:30 AM
コンパイラの挙動が違う可能性があるね
Avatar
ありそう
Avatar
Avatar
omochimetaru
class Test { func test1(_ f: @MainActor @escaping () async -> Void) { Task.detached { await f() } } func test2(_ f: @escaping () async -> Void) { test1(f) } func main() async { let _: Void = await withUnsafeContinuation { c in test2 { print(Thread.current) c.resume(returning: ()) } } let _: Void = await withUnsafeContinuation { c in test2 { @MainActor () in print(Thread.current) c.resume(returning: ()) } } } } // AppDelegate func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { Task.detached { await Test().main() } return true } (edited)
omochimetaru 3/3/2022 11:30 AM
この自分のやつはtest1とtest2はメソッド
Avatar
@swift-5.5.3 -Xfrontend -parse-as-library import Foundation @main struct Entrypoint { static func main() async throws { print("in main():", Thread.current, Thread.isMainThread) await MainActor.run { print("in MainActor.run:", Thread.current, Thread.isMainThread) } } }
Avatar
Avatar
Yuta Saito
@swift-5.5.3 -Xfrontend -parse-as-library import Foundation @main struct Entrypoint { static func main() async throws { print("in main():", Thread.current, Thread.isMainThread) await MainActor.run { print("in MainActor.run:", Thread.current, Thread.isMainThread) } } }
in main(): <Thread: 0x000000000ab51790> true in MainActor.run: <Thread: 0x000000000ab51790> true
Avatar
ありゃ、これ手元のLinuxで↓になるんですよね in main(): <Thread: 0x000055ec99acfd90> true in MainActor.run: <Thread: 0x00007fca74000bf0> false (edited)
11:36 AM
つまり、MainActorに居てもisMainThreadがtrueとは限らないんじゃないかと疑ったんですが、botだとその可能性はなさそう (edited)
Avatar
omochimetaru 3/3/2022 11:55 AM
ふむー
Avatar
norio_nomura 3/4/2022 4:02 AM
@swift-5.5.3 -Xfrontend -parse-as-library @swift-5.6.3 -Xfrontend -parse-as-library @swift-main -Xfrontend -parse-as-library import Foundation @main struct Entrypoint { static func main() async throws { print("in main():", Thread.current, Thread.isMainThread) await MainActor.run { print("in MainActor.run:", Thread.current, Thread.isMainThread) } } } (edited)
Avatar
Avatar
norio_nomura
@swift-5.5.3 -Xfrontend -parse-as-library @swift-5.6.3 -Xfrontend -parse-as-library @swift-main -Xfrontend -parse-as-library import Foundation @main struct Entrypoint { static func main() async throws { print("in main():", Thread.current, Thread.isMainThread) await MainActor.run { print("in MainActor.run:", Thread.current, Thread.isMainThread) } } } (edited)
swift55 BOT 3/4/2022 4:02 AM
in main(): <Thread: 0x0000000009dd57c0> true in MainActor.run: <Thread: 0x0000000009dd57c0> true
Avatar
Avatar
norio_nomura
@swift-5.5.3 -Xfrontend -parse-as-library @swift-5.6.3 -Xfrontend -parse-as-library @swift-main -Xfrontend -parse-as-library import Foundation @main struct Entrypoint { static func main() async throws { print("in main():", Thread.current, Thread.isMainThread) await MainActor.run { print("in MainActor.run:", Thread.current, Thread.isMainThread) } } } (edited)
swiftNightly BOT 3/4/2022 4:02 AM
in main(): <Thread: 0x000000000bb0d200> true in MainActor.run: <Thread: 0x00007f3f14000c40> false
Avatar
omochimetaru 3/4/2022 4:04 AM
MainActor.run でメインスレッドじゃないのかー
Avatar
norio_nomura 3/4/2022 4:05 AM
nightlyがおかしいの?
Avatar
なるほどおかしい
Avatar
Avatar
norio_nomura
@swift-5.5.3 -Xfrontend -parse-as-library @swift-5.6.3 -Xfrontend -parse-as-library @swift-main -Xfrontend -parse-as-library import Foundation @main struct Entrypoint { static func main() async throws { print("in main():", Thread.current, Thread.isMainThread) await MainActor.run { print("in MainActor.run:", Thread.current, Thread.isMainThread) } } } (edited)
swift56 BOT 3/4/2022 4:08 AM
in main(): <Thread: 0x000000000bd3c440> true in MainActor.run: <Thread: 0x000000000bd3c440> true
4:24 AM
実装は @MainActor の作用に任されている?
Avatar
omochimetaru 3/4/2022 4:25 AM
ウオ、いじっとる
Avatar
↑のOtherActor.runの形じゃ無くなってる
4:26 AM
c++ /// Enqueues a task on the main executor. SWIFT_CC(swift) static void swift_task_enqueueMainExecutorImpl(Job *job) { // The cooperative executor does not distinguish between the main // queue and the global queue. swift_task_enqueueGlobalImpl(job); }
4:26 AM
あ、こっちじゃないか・・・?
4:27 AM
c++ SWIFT_CC(swift) static void swift_task_enqueueMainExecutorImpl(Job *job) { assert(job && "no job provided"); JobPriority priority = job->getPriority(); // This is an inline function that compiles down to a pointer to a global. auto mainQueue = dispatch_get_main_queue(); dispatchEnqueue(mainQueue, job, (dispatch_qos_class_t)priority, mainQueue); }
Avatar
これはMainActorにホップする時に呼ばれるやつ
Avatar
omochimetaru 3/4/2022 4:28 AM
MainActor._enqueue から辿っていったらここに来そうだった
4:28 AM
CooperativeGlobalExecutor.incswift_task_enqueueMainExecutorImpl はなんなんだろう
4:28 AM
@MainActor の呼び出しを MainActor._enqueue に変換する処理はコード生成なんかな
Avatar
アクターのホップポイントは、SILの時点でhop_to_executorになっていて、 (edited)
4:35 AM
IRGenでswift_future_ なんちゃらAPIの呼び出しになる。enqueueはその中で呼ばれてるはず (edited)
4:36 AM
だから、MainActor.runの実装のSILを見て、hop_to_executorの有無を確認したい
Avatar
omochimetaru 3/4/2022 4:38 AM
なるほどなるほど
Avatar
Asynchronous functions isolated to global actors hop to the global at the beginning of the function but do not hop back on return.
https://github.com/apple/swift/pull/39872 あれ、認識間違ってたかも
(edited)
Avatar
omochimetaru 3/4/2022 4:44 AM
お。
Avatar
@swift-main -Xfrontend -parse-as-library import Dispatch import Foundation func checkIfMainQueue(expectedAnswer expected: Bool) { dispatchPrecondition(condition: expected ? .onQueue(DispatchQueue.main) : .notOnQueue(DispatchQueue.main)) } @main struct Entrypoint { static func main() async throws { print("in main():", Thread.current, Thread.isMainThread) checkIfMainQueue(expectedAnswer: true) await MainActor.run { print("in MainActor.run:", Thread.current, Thread.isMainThread) checkIfMainQueue(expectedAnswer: true) } } } (edited)
Avatar
Avatar
Yuta Saito
@swift-main -Xfrontend -parse-as-library import Dispatch import Foundation func checkIfMainQueue(expectedAnswer expected: Bool) { dispatchPrecondition(condition: expected ? .onQueue(DispatchQueue.main) : .notOnQueue(DispatchQueue.main)) } @main struct Entrypoint { static func main() async throws { print("in main():", Thread.current, Thread.isMainThread) checkIfMainQueue(expectedAnswer: true) await MainActor.run { print("in MainActor.run:", Thread.current, Thread.isMainThread) checkIfMainQueue(expectedAnswer: true) } } } (edited)
swiftNightly BOT 3/4/2022 4:50 AM
in main(): <Thread: 0x000000000a8d75b0> true in MainActor.run: <Thread: 0x00007f6f54000c40> false (edited)
Avatar
テストケース見てると、↑みたいにDispatchQueue.mainにいるかを検証していて、Thread.isMainThreadは見ていない模様
4:52 AM
そしてメインスレッドではないがDispatchQueue.main上にいる。
Avatar
omochimetaru 3/4/2022 4:52 AM
main queueがスレッドを移動する?
4:52 AM
@mainfunc main async が変な挙動するのかな
Avatar
omochimetaru 3/9/2022 4:01 AM
Hello Swift community, The review of SE-0345 "if let shorthand for shadowing an existing optional variable" begins now and runs through March 22, 2022. 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 revi...
4:01 AM
短縮if letの審査開始
Avatar
Kishikawa Katsumi 3/9/2022 4:03 AM
これはスッと決まりそうだな。
Avatar
omochimetaru 3/9/2022 4:04 AM
これって超初期から、「よく聞かれるけどやらないよ」って言ってたアイデアなんですけど
4:04 AM
最近しばらくずっとスレッドが盛り上がっていて
4:04 AM
この前のラトナー引退のときもこのスレでのやり取りが引用されてたんですよね
4:09 AM
流れが変わってるなあ
Avatar
Kishikawa Katsumi 3/9/2022 4:09 AM
そうなんだ。
Avatar
スレ建ったときはシンプルじゃなくなるから却下、で終わりだと思ってたのに
Avatar
Kishikawa Katsumi 3/9/2022 4:11 AM
まあLattnerさんの話を除外してもSwiftの見た目の文法は初期の頃とはだいぶ変わってるから拒否感はなくなってるとか。
4:11 AM
今さらシンプルじゃなくなるって言われてもねえ、、、みたいな。
4:11 AM
むしろシンプルやん。
Avatar
omochimetaru 3/9/2022 4:12 AM
ある変数の型は let で定義した時から固定って考え方なんですよね
4:12 AM
この文法を導入してしまうと、
4:12 AM
同じ変数のままなのに型が変わるっていうSwiftには無かった概念が出てくる (TypeScriptのフローキャストのような感じになる)
4:12 AM
のと、 代入の省略記法なのか、変数の型変化なのかが文法上わからないから
4:13 AM
この変数が inout だったりしたときに、どうなるのかよくわからない
4:13 AM
if let 後に代入したら、元の変数も変化するのか、それとも分離された変数になっているのか。
Avatar
Kishikawa Katsumi 3/9/2022 4:13 AM
let a = a, の左辺で変わるというのが今までの動作だけど let a で変わると混乱ってことか。 (edited)
Avatar
omochimetaru 3/9/2022 4:13 AM
そうそう。そこに代入文の形になっていて、型変化の前後で別物として分離されているというセマンティクスが
4:14 AM
省略記法を導入すると(見た目から)よくわからなくなる。 (edited)
4:14 AM
Swiftの見た目の文法は初期の頃とはだいぶ変わってる
↑これは一理ありますね。property wrapperとか、dynamic keypath とか、 result builder とか、もう見た目からは動作がさっぱり想像できないやついっぱいできちゃったw
(edited)
Avatar
別の変数に関する定義と使用が同じ箇所にあるのがなぁ
Avatar
omochimetaru 3/9/2022 4:15 AM
こういうのはScalaの周辺の議論でよく言われるのは easy と simple の違いってやつで
Avatar
Kishikawa Katsumi 3/9/2022 4:16 AM
省略したら分かりにくくなる、は妥当なんですけど、 それは省略だからlet a = a,の右辺が省略されてるんですよ、で解決してしまうな。
Avatar
omochimetaru 3/9/2022 4:16 AM
このif let 省略はいわゆる、easy だけど simple ではない タイプの機能ですね
Avatar
Kishikawa Katsumi 3/9/2022 4:16 AM
もっと決定的な衝突とかがないと難しそう。
Avatar
Avatar
Kishikawa Katsumi
省略したら分かりにくくなる、は妥当なんですけど、 それは省略だからlet a = a,の右辺が省略されてるんですよ、で解決してしまうな。
omochimetaru 3/9/2022 4:17 AM
そうですね。 「知識が無いと読み解けない文法はこれに始まった事じゃないし、同名への代入って事を知っておけばいいだけじゃん」的なことをairspeedswiftさんが書いてた気がする
Avatar
Kishikawa Katsumi 3/9/2022 4:20 AM
まあなんか2回書きたくないっていう考え方はけっこうあるよね。 JSのJSON記法もそういう省略あるし。
Avatar
omochimetaru 3/9/2022 4:20 AM
inoutで使った場合みたいなコーナーケースの混乱を気にするより、 多くの場合で楽に書けるようになるメリットのほうが大きいじゃん的な
Avatar
if var x も一緒に入るんですかこれ?
4:23 AM
if let foo { ... } if var foo { ... } あった
Avatar
omochimetaru 3/9/2022 4:24 AM
if let foo { ... } if var foo { ... } else if let foo { ... } else if var foo { ... } guard let foo else { ... } guard var foo else { ... } while let foo { ... } while var foo { ... }
4:24 AM
Detailed Designのとこに↑こんなのが
Avatar
if let foo.bar { ... } // 🛑 これはダメと
Avatar
omochimetaru 3/9/2022 4:26 AM
Alternatives considered if foo if unwrap foo if let foo? if foo != nil if var foo は無し
4:26 AM
議論読んでないけどこれらは検討却下済みのようだ
Avatar
Kishikawa Katsumi 3/9/2022 4:27 AM
if fooは衝突するよな。Bool的なやつと
🦀 1
Avatar
omochimetaru 3/9/2022 4:27 AM
Author の Cal Stephens さんは airbnb の人らしい
Avatar
if let foo? いいなと思ったけど if let foo?: Foo 型アノテーション付けにくいとのこと
Avatar
Kishikawa Katsumi 3/9/2022 4:27 AM
省略とは違うから別でやってほしいけど、 if foo != nil でfooがオプショナル外れるのはほしいな
kotlin 1
Avatar
IDEが = fooを薄く表示してくれれば混乱は減りそう
Avatar
IntelliJっぽい
4:36 AM
いいよね
Avatar
omochimetaru 3/9/2022 4:37 AM
Xcodeくんガタガタだからなあ
t_kusa 1
Avatar
Kishikawa Katsumi 3/9/2022 4:43 AM
それだ。それ最高だ。
Avatar
Avatar
Kishikawa Katsumi
省略とは違うから別でやってほしいけど、 if foo != nil でfooがオプショナル外れるのはほしいな
そういう Smart Cast 的なやつは、宣言箇所にジャンプしたときに型を確認できないからやらないって話が、前に別の文脈であったような。何の機能のときだっけな。
Avatar
Kishikawa Katsumi 3/10/2022 3:29 AM
なるほど。それもわかる。まあだいたいはif letかguard letでいいし。どういうときに欲しいと思ったんだったかな。。。?
Avatar
何か思い出せないんですが、ProposalかForumかの議論で、何かの機能について話してる中で、(多分Core Teamの誰かに)↑の理由が挙げられてたはずなんですよね。何も思い出せてなくてすみませんが💦
Avatar
Kishikawa Katsumi 3/10/2022 3:34 AM
いえいえ。すでに議論済みだとは思ってました。理由がわかって興味深いです。
Avatar
omochimetaru 3/12/2022 8:23 AM
Hello, Swift community. The review of SE-0346: Lightweight same-type requirements for primary associated types begins now and runs through March 29th, 2022. 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 ...
8:23 AM
プロトコルのprinary associated typeをangle bracketで書ける提案が審査入り
8:30 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0346-light-weight-same-type-syntax.md at main · apple/swift-evolution
8:32 AM
将来ありえるジェネリックプロトコルの文法を奪ってしまう問題については提案書で言及されてた
8:36 AM
途中までは何言ってるかわかるが最後の段落の
Nothing in this proposal precludes …
が、英語が読み解けない、、
Avatar
if let x くらいならいいんですけれど、過去の互換のために associatedTypeProgocol<E>みたいなのが混在するのは混乱しそう… (edited)
11:36 AM
でもmotivationを見ると結構よさそうですね
Avatar
Avatar
quesera2
if let x くらいならいいんですけれど、過去の互換のために associatedTypeProgocol<E>みたいなのが混在するのは混乱しそう… (edited)
omochimetaru 3/12/2022 1:14 PM
この前やってた any キーワードの話とかと合わせると、 AnySequence<Element> の代わりに any Sequence<Element> とか書けるようになって、 これは直感的だし便利ですよね。
t_tashikani 1
1:15 PM
AnySequence はライブラリ実装だけど any Sequence は言語機能だし。
Avatar
Avatar
omochimetaru
途中までは何言ってるかわかるが最後の段落の
Nothing in this proposal precludes …
が、英語が読み解けない、、
Nothing in this proposal precludes introducing generic protocols in the future under a different syntax
このプロポーザルの提案が将来的に異なる構文でジェネリックプロトコルを導入することを不可能にするわけではない くらいの感じ?で、例として↓のような構文が挙げられていると。 protocol Convertible(from: Self, to: Other) { static func convert(_: Self) -> Other } extension Convertible(from: String, to: Int) { static func convert(_: String) -> Int } extension Convertible(from: String, to: Double) { static func convert(_: String) -> Int }
Avatar
Opaque result typeのassociated typeを指定できるようになるの良さそうですね。 https://github.com/pointfreeco/swift-parsing/blob/e7c65755c5634bd0ab4edd076c8b1b442f71457d/Sources/Parsing/Parser.swift#L231-L275
Avatar
あれ、これって糖衣だけかと思ってたんですがORTに型パラ埋められるんですか
1:03 AM
eraseToAnyPublisherを大幅に減らせる?
Avatar
かなり要らなくなりそう
Avatar
Avatar
Iceman
あれ、これって糖衣だけかと思ってたんですがORTに型パラ埋められるんですか
実はしれっと入っていて、pitch段階では「これ別のプロポーザルにするべきでは?」みたいな話も確か出ていたと思いますw https://github.com/apple/swift-evolution/blob/main/proposals/0346-light-weight-same-type-syntax.md#constrained-protocols-in-opaque-result-types (edited)
Avatar
なるほどw ORTにwhereつけられるの嬉しいですが、これである必要ないですもんね。 糖衣の部分は必要かどうか怪しいけど、ORTは明確にほしい
Avatar
Avatar
koher
Nothing in this proposal precludes introducing generic protocols in the future under a different syntax
このプロポーザルの提案が将来的に異なる構文でジェネリックプロトコルを導入することを不可能にするわけではない くらいの感じ?で、例として↓のような構文が挙げられていると。 protocol Convertible(from: Self, to: Other) { static func convert(_: Self) -> Other } extension Convertible(from: String, to: Int) { static func convert(_: String) -> Int } extension Convertible(from: String, to: Double) { static func convert(_: String) -> Int }
omochimetaru 3/13/2022 3:59 AM
あー、その構文がよくわからなかったんですが、プロトコル名の後ろに丸括弧でパラメータを与えているんですね
Avatar
ORTにwhereつけられる
そういえばNamed opaque result typesってまだ途中なんですね。もう完了しているのかと思ってました。 https://github.com/apple/swift/pull/40715
(edited)
Implement support for named opaque result types, e.g., func f() -> <T: Hashable & P, U where U: Q> [T: U] { ... } this mostly involves wiring up name lookup and type resolution so we c...
Avatar
@rethrows public protocol AsyncIteratorProtocol { mutating func next() async throws -> Self.Element? } こんなrethrowsの書き方があるんですね…
Avatar
Kishikawa Katsumi 3/14/2022 1:30 AM
@rethrows ってAttributeがあったのか、と思って調べてたら https://www.pointfree.co/blog/posts/73-parser-errors なんか最近入った?まだExperimentalなものらしいですね。
A new release of swift-parsing that brings delightful and informative error messaging to parser failures.
🙏🏻 1
Avatar
関数側じゃなくてプロトコルに付いてるのは初めて見た気がしたんですけれど、まだ実験段階なのですね プロトコルがrethrowsするみたいでちょっと違和感…!
Avatar
Kishikawa Katsumi 3/14/2022 1:36 AM
@dgregor79 @stephencelis You can enable the feature by adding a @rethrows attribute on the protocol, but it's not "officially supported"
1:36 AM
Hey all, Here's a pitch for a feature that @Philippe_Hausler, @Joe_Groff, @Tony_Parker and I have been thinking about to make rethrows also work for protocol conformances. It's motivated by some of the concurrency work, but is separable and useful on its own. Philippe has been prototyping it in the compiler so we have a fairly good sense that t...
1:36 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/NNNN-rethrows-protocol-conformances.md at rethrows-protocol-conformances · Do...
1:37 AM
このあたりが関連する議論のようですね。
Avatar
The Swift.org site has long served as the hub where developers come together to work on the open source Swift compiler, libraries, and tools. Today, we are happy to announce that the Swift.org website itself is also an open source project, ready for community contributions. With this move, the website is also expanding its mandate to better supp...
12:14 PM
ウェブサイトも開かれることでいい感じで人材が集まるといいですね~という感じですけれど、8年経ってようやくというのがもにょい感じですね
Avatar
Swift.org、Jekyll製なんですね。 https://github.com/apple/swift-org-website/ (edited)
Avatar
omochimetaru 3/24/2022 2:44 AM
Full proposal: swift-experimental-string-processing/RegexBuilderDSL.md at main · apple/swift-experimental-string-processing · GitHub Regex builder DSL Status: Pitch Implementation: apple/swift-experimental-string-processing Table of Contents Introduction Motivation Proposed solution Detailed design RegexComponent protocol Concatenati...
2:45 AM
正規表現をResultBuilder上で構成して、
2:45 AM
その式中に含まれるCapture Listの数を、
2:45 AM
静的に型パラメータとして構成するライブラリの提案があって
2:46 AM
これ前に話題に出た時、実装しようと思うと、CaptureListの合成する部分がめっちゃ大変な事になるんじゃないかなとなんとなく思ったんだけど
2:46 AM
Hi all, While working on the RegexBuilder-based DSL with strongly-typed regex captures, we’ve come across an issue with where concatenating the component types in a result builder block as a tuple would involve a factorial explosion of buildBlock overloads and unreasonably long compilation time, and it isn't something that could be trivially re...
2:47 AM
まず、ResultBuilderに対して、他引数のbuildBlockの代わりに、
2:47 AM
2引数のbuildPartialBlockの複数の呼び出しに変換するAPIを用意した上で
2:48 AM
結合する2つの正規表現式の、左側と右側のキャプチャ要素数の組み合わせに対して
2:49 AM
二乗の組み合わせ全部をオーバーロードする力技を提案しててビックリした
2:49 AM
extension RegexComponentBuilder { public static func buildPartialBlock<W0, W1, C0, R0: RegexComponent, R1: RegexComponent>( accumulated: R0, next: R1 ) -> Regex<(Substring, C0)> where R0.Output == W0, R1.Output == (W1, C0) { .init(node: accumulated.regex.root.appending(next.regex.root)) } }
2:49 AM
↑これは 左側がキャプチャ0個、右側がキャプチャ1個
2:50 AM
public static func buildPartialBlock<W0, W1, C0, C1, R0: RegexComponent, R1: RegexComponent>( accumulated: R0, next: R1 ) -> Regex<(Substring, C0, C1)> where R0.Output == W0, R1.Output == (W1, C0, C1) { .init(node: accumulated.regex.root.appending(next.regex.root)) } public static func buildPartialBlock<W0, W1, C0, C1, C2, R0: RegexComponent, R1: RegexComponent>( accumulated: R0, next: R1 ) -> Regex<(Substring, C0, C1, C2)> where R0.Output == W0, R1.Output == (W1, C0, C1, C2) { .init(node: accumulated.regex.root.appending(next.regex.root)) } ...
Avatar
いまのResultBuilderも
Avatar
omochimetaru 3/24/2022 2:50 AM
public static func buildPartialBlock<W0, W1, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, R0: RegexComponent, R1: RegexComponent>( accumulated: R0, next: R1 ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.Output == W0, R1.Output == (W1, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appending(next.regex.root)) } ↑ここまでは左側0個 (edited)
2:50 AM
public static func buildPartialBlock<W0, W1, C0, C1, R0: RegexComponent, R1: RegexComponent>( accumulated: R0, next: R1 ) -> Regex<(Substring, C0, C1)> where R0.Output == (W0, C0), R1.Output == (W1, C1) { .init(node: accumulated.regex.root.appending(next.regex.root)) } ↑ここからは左側1個
2:50 AM
An early experimental general-purpose pattern matching engine for Swift. - swift-experimental-string-processing/Variadics.swift at main · apple/swift-experimental-string-processing
Avatar
2引数buildBlockを作っておいてかつ
Avatar
omochimetaru 3/24/2022 2:51 AM
「パラメータ数の合計が10個」をアッパーにとってるから、100(10x10)通りよりは少ないけど。
Avatar
雪だるまジェネリクスを解釈できるようにするとオーバーロード力業解決のアプローチが出来るよ
Avatar
omochimetaru 3/24/2022 2:52 AM
2引数しか定義してない状態で3行書いたらどうなるの?
Avatar
M<M<A,B>,C> か M<A,M<B,C>> になる
Avatar
omochimetaru 3/24/2022 2:52 AM
あ、頑張って2引数の繰り返しに畳んでくれる仕様はあるのか。
Avatar
この時にbuildBlockの第一引数、第二引数に制約を課すことで
2:53 AM
オーバーロードに指向性を持たせたり出来るよ
Avatar
omochimetaru 3/24/2022 2:53 AM
ただまあ雪だるま型だと、最終的なAPIでアクセスするときに、その構造を歩かないといけないから
2:53 AM
正規表現のキャプチャリストとしては使いにくいね
Avatar
雪だるまを解くのは、実は賢い方法があって
2:55 AM
protocol Node と protocol KindA があるときに
2:55 AM
末端にKindAがあればNodeにKindAの機能を持たせる、みたいなのは一応書ける
2:56 AM
extension Node: KindA where Element: KindA と書けば、多重にネストしてても連鎖してNodeがKindAの機能を持てるので
2:56 AM
ただし、Nodeが2要素持つとこれは使えなくなる
2:57 AM
buildPartialBlockはその辺りを綺麗にしたい感じのAPIなのかな
Avatar
omochimetaru 3/24/2022 2:57 AM
リスト的なものだと2要素以上もつんじゃない?
2:57 AM
Regex { regex0 // Regex<Substring> regex1 // Regex<(Substring, Int)> if condition { regex2 // Regex<(Substring, Float)> } else { regex3 // Regex<(Substring, Float)> } } // Regex<(Substring, Int, Float)>
Avatar
そうだね、なので連鎖して解けるためには指向性を持たせた雪だるまにしないといけない
Avatar
omochimetaru 3/24/2022 2:58 AM
Regex { let e0 = RegexComponentBuilder.buildExpression(regex0) // Component<Regex<Substring>> let e1 = RegexComponentBuilder.buildExpression(regex1) // Component<Regex<(Substring, Int)>> let e2: Regex<(Substring, Float)> if condition { let comp = RegexComponentBuilder.buildExpression(regex2) // Component<Regex<(Substring, Float)>> e2 = RegexComponentBuilder.buildEither(first: comp) // Regex<(Substring, Float)> } else { let comp = RegexComponentBuilder.buildExpression(regex3) // Component<Regex<(Substring, Float)>> e2 = RegexComponentBuilder.buildEither(first: comp) // Regex<(Substring, Float)> } let r0 = RegexComponentBuilder.buildPartialBlock(first: e0) let r1 = RegexComponentBuilder.buildPartialBlock(accumulated: r0, next: e1) let r2 = RegexComponentBuilder.buildPartialBlock(accumulated: r1, next: e2) return r2 } // Regex<(Substring, Int, Float)>
2:58 AM
partialBlockは reduceの s += x みたいな形にする
2:58 AM
だから2つの場合の合成を書ければ、N段の合成が書けるようになる
2:59 AM
ただ2つの場合において、左と右のタプル要素数の組み合わせに対応するために、たくさんオーバーロード書かないといけないという話
Avatar
ふむー
2:59 AM
雪だるまを上手に書けばかなりサボれるんじゃん?と思ったけど
2:59 AM
そうもいかないのかな
Avatar
omochimetaru 3/24/2022 3:00 AM
そもそも最終的に出てくるものを Regex<(Substring, Int, Float)> にしたいよね (edited)
Avatar
いまのbuildBlockだと3要素以上並んだときに雪だるま作れなくないですか?
3:01 AM
組み合わせの要素数乗のオーバーロードを用意するのは別として
3:02 AM
あ、そういう仕様がある?
Avatar
あれ、出来なかったか?
3:03 AM
自信なくなってきたw
Avatar
Avatar
omochimetaru 3/24/2022 3:07 AM
俺の記憶だとできなくて
3:07 AM
SwiftUIは11個のViewを直列に並べられないよね
3:07 AM
10個までしかオーバーロードが無いから
Avatar
確かに、これが可能なら11個の時にネストして組み立てれるはずですね
3:13 AM
じゃあ別の話と勘違いしているわ
Avatar
じゃあなるほど、buildPrtialBlockというのが、任意の行をreduceに食わせて、必要によっては雪だるまを作れるようにするためのものなのか
Avatar
omochimetaru 3/24/2022 7:27 AM
そうだね。buildPartialBlockの実装次第では一段ごとにジェネリクスを深くしていくこともできる。
7:28 AM
で、段数の制限はない。
Avatar
buildEitherでswitch文を作る仕組みは元々そうだったし、良い感じがしますね
7:34 AM
こうなってくるとやはり、可変長ジェネリクスが欲しくなってくるなぁ
7:34 AM
雪だるまはworkaroundの感が否めない
Avatar
AsyncSequence使った新しいpackageが出ましたね👀 https://github.com/apple/swift-async-algorithms
Async Algorithms for Swift. Contribute to apple/swift-async-algorithms development by creating an account on GitHub.
👀 1
Avatar
operator使えるようになるのですね~ CombineよりAsyncSequenceみたいになるんでしょうか…
Avatar
どうなるんですかねー。Dougさんは「いずれは…」的なことを前言ってましたね。 https://www.swiftbysundell.com/podcast/99/
Avatar
AsyncSequence ベースの @PublishedObservableObject はこれの外側で扱うことになるんでしょうか?
Avatar
> AsyncSequence ベースの @Published や ObservableObject はこれの外側で扱うことになるんでしょうか?
すいませんコメントに気がついてませんでした💦 この辺りで言及されてますね👀 There are obviously a few key areas that this package does not touch on (e.g. @Published or ObservableObject since those interact more so with SwiftUI than anything else) https://forums.swift.org/t/introducing-swift-async-algorithms/56231/3 That boundary is not really part of this project and more so something the folks working on SwiftUI are more equipped to tackle. https://forums.swift.org/t/introducing-swift-async-algorithms/56231/8
(edited)
12:22 AM
全然上と関係ない話ですが、 MainActor周りはどのバージョンで何が修正されているのかを把握するのが難しいですねw MainActorクラス内の関数がMain Threadで実行されない(Swift5.6で修正) MainActor isolation is not ensured https://bugs.swift.org/browse/SR-15789 MainActorクラスのMainActorではないinitがMainActorで守られていない(Swift5.7で修正) MainActor doesn't cascade to init in class https://bugs.swift.org/browse/SR-15694 https://forums.swift.org/t/mainactor-doesnt-work-or-misunderstood/56222 (edited)
Avatar
Avatar
shiz
> AsyncSequence ベースの @Published や ObservableObject はこれの外側で扱うことになるんでしょうか?
すいませんコメントに気がついてませんでした💦 この辺りで言及されてますね👀 There are obviously a few key areas that this package does not touch on (e.g. @Published or ObservableObject since those interact more so with SwiftUI than anything else) https://forums.swift.org/t/introducing-swift-async-algorithms/56231/3 That boundary is not really part of this project and more so something the folks working on SwiftUI are more equipped to tackle. https://forums.swift.org/t/introducing-swift-async-algorithms/56231/8
(edited)
ありがとうございます!
🙂 1
Avatar
omochimetaru 4/5/2022 6:14 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0348-buildpartialblock.md at main · apple/swift-evolution
6:14 AM
buildPartialBlock採択
Avatar
swiftuiの行制限がなくなるね
6:18 AM
既存のbuildBlockはあんまり使わなくなりそうだ
Avatar
これでViewを11個以上並べられるぞ!って思ったけどViewBuilderにbuildPartialBlockの実装が必要だからiOS13には出せないか (edited)
Avatar
iOS13かつ11個並べたときだけエラー出るみたいな世界観になりそう
Avatar
buildBlockとbuildPartialBlockは両立するのかな?
6:21 AM
あ、でも@unavalilable が今あるか
Avatar
buildBlockの方を優先する作りにしてれば問題は起きなさそう
Avatar
omochimetaru 4/5/2022 6:23 AM
SwiftUIは TupleView<(A, B, C)>TupleView<(A, B, C, D)> みたいにタプルが伸びていくようになってて再帰的定義ではないから
6:24 AM
結局 buuildPartialBlock を使って、 3個から4個、 4個から5個、... ってオーバーロードしておいた数までしか作れないんじゃないかな。
Avatar
TupleView2<A,B>が作られてそれがメインに使われると予想しています
Avatar
omochimetaru 4/5/2022 6:24 AM
タプルを伸ばすんじゃなくて再帰的な型ツリーにする方針になるなら制限がなくなるね。
Avatar
既存のTupleView、作りも無理があるので2要素にした方がグラフ解析の面でもメリットありそう
Avatar
omochimetaru 4/5/2022 12:46 PM
Hello, Swift community. The review of SE-0351: Regex Builder DSL begins now and runs through April 15, 2022. This review is part of a collection of proposals for better string processing in Swift. The proposal authors have put together a proposal overview with links to in-progress pitches and reviews. This proposal builds on the Regex type be...
12:47 PM
型安全正規表現の審査が来た
12:47 PM
展開が早い
12:48 PM
さっきのbuildPartialBlockを踏まえたやつ
Avatar
omochimetaru 4/7/2022 3:45 PM
Hi everyone. The review of SE-0352: Implicitly Opened Existentials begins now and runs through April 18th, 2022. 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 by direct m...
3:45 PM
暗黙existential openの審査来た
Avatar
This organization is used for migrating issue from bugs.swift.org to GitHub Issues. - Swift Bugs Migration
3:43 AM
日曜日の夜に...
🔥 1
Avatar
invitation来てた
3:47 AM
なんでinvitation必要なんだ?
🤔 1
Avatar
偽物の可能性
Avatar
omochimetaru 4/11/2022 3:50 AM
invitationするって説明合ったよ
Avatar
うかつにポチッと押してしまった 🙃
Avatar
omochimetaru 4/11/2022 3:50 AM
Actions required Update Github and JIRA (bugs.swift.org 448) username mapping on forums.swift.org by April 7th 2022 Go to profile preferences - Swift Forums Update JIRA Username and GitHub Username Accept the invitation to “swift-issues-migration” organization on GitHub by April 18th 2022 The invitation will be sent by April 7th 2022
Avatar
Accept the invitation to “swift-issues-migration” organization on GitHub by April 18th 2022 The invitation will be sent by April 7th 2022
3:50 AM
Swift bugs are moving to GitHub Issues and we need your help! Swift's open source project issues are currently in JIRA, making it difficult for developers to discover and integrate them into our workflows on GitHub, such as pull requests. To provide a better workflow for developers, we are working on migrating JIRA to GitHub Issues. The issues ...
3:51 AM
まだ本物とはわからないけれど多分本物かなあ
Avatar
omochimetaru 4/11/2022 3:51 AM
これが来てるってことはforum profile欄のGitHubユーザ名の設定は成功してる
Avatar
同じことを第三者がやろうとしてもできる
Avatar
まあ既に入ってるメンバーの人々から見て本物でしょう
Avatar
omochimetaru 4/11/2022 3:51 AM
org名の swift-issues-migration があってるから本物でしょう
Avatar
入らないと見えないんだよなあ > 誰がいるか (edited)
Avatar
omochimetaru 4/11/2022 3:51 AM
3:52 AM
Avatar
名前は誰でも自由にとれる気がする? (edited)
Avatar
omochimetaru 4/11/2022 3:52 AM
↑入ったらURL欄で見れた
3:52 AM
URLだから重複できないでしょ
3:52 AM
表示名の Swift Bugs Migration のほうはなりすませそう。
Avatar
swift-bugs-migrationっていうのを第三者が作ることはできるかなっていう話。
Avatar
forumのアナウンスより前にorgが作られてたかを検証すればよさそう
Avatar
それなー
3:53 AM
わかんないんだよなあ
Avatar
えー
Avatar
created_atみたいなのある? apiとかならあるのかな
3:54 AM
"created_at": "2022-03-18T17:18:01Z"
Avatar
おー、あった。
Avatar
omochimetaru 4/11/2022 3:54 AM
おお
Avatar
forumのポスト= Mar 21, 4:44 PM (edited)
3:55 AM
大丈夫そうだ
Avatar
すでに test という名前のリポジトリに (多分お試しで) issues がマイグレーションされてますね.Author がマネキンなものとそうでないものの違いが気になります...
Avatar
Hello, Swift community. The second review of SE-0346 ended on April 12th. This round of review was narrowly focused on the changes to the proposal made after the first review, which are summarized at the start of the review thread. Feedback on the revised proposal was overall positive. Some community members maintained their misgivings about...
👏🏻 2
11:22 AM
Collection<Int> 採択
Avatar
associatedtypeを定義に明記する(補足: <>の中には書かない)に変わってからはみんな賛成って流れでしたね。 (edited)
wakaru 1
Avatar
omochimetaru 4/14/2022 1:46 PM
第二審査でそこが変わってたのか。なるほどー
Avatar
↑のany版もreviewになってましたね。 https://forums.swift.org/t/se-0353-constrained-existential-types/56853
Hi everyone. The review of SE-0353: Constrained Existential Types begins now and runs through May 3, 2022. 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 by direct messa...
Avatar
似たようなのたくさんあってややこしい
t_wakaru 1
Avatar
omochimetaru 4/22/2022 7:15 AM
このへんいろいろ進んだから まとめて発表しようかなと思ってる
Avatar
ちゃんと読み込めてないところもあるけど明日 #swift-zoomin で話す予定。
Avatar
omochimetaru 4/22/2022 7:16 AM
Avatar
Proposalの紹介よりも、それらを交えつつSwiftらしいプロトコルの使い方というテーマで実演しながら話す感じだけど。
Avatar
omochimetaru 4/22/2022 7:18 AM
とりあえず明日聞いてみて判断しよう。
Avatar
Proposalの内容中心のは、今レビュー中のもかたまってから、iOSDCとかで話すと良さそうだなと考えてた。
Avatar
omochimetaru 4/22/2022 7:19 AM
ところで、
7:19 AM
このあたりのAPIが充実してくると
7:19 AM
Java的な、 List<Int> でなるべく取り回すっていう流派が生じそうだけど
7:19 AM
そのへんどうおもってます?
Avatar
それはできるようになるけど、あくまでこれまで通りの使い方がメインかなぁと思ってます。 any が導入された主旨にも沿うかと。
Avatar
omochimetaru 4/22/2022 7:20 AM
↓誤植 Desckset (edited)
🙏 1
7:21 AM
あ、治ってた、これは過去の開催の説明文だ
Avatar
人間が読み書きするときは抽象度が高く、取り回しの良い型で、機械が取り扱うときはstrictな型になる、そんな感じの世界観になっていくんじゃないかと思う
7:22 AM
ORTとか正にそんな感じだし (edited)
Avatar
Avatar
tarunon
人間が読み書きするときは抽象度が高く、取り回しの良い型で、機械が取り扱うときはstrictな型になる、そんな感じの世界観になっていくんじゃないかと思う
omochimetaru 4/22/2022 7:22 AM
じゃあ、これまで [Int] を受け取っていたような状況では any Sequence<Int> を受け取るように変わるということ?
Avatar
少なくともArrayである必要が無い場面は、そうなるんじゃないか
Avatar
some Sequence<Int> じゃないかなぁ。
Avatar
someだね
7:23 AM
そう
Avatar
omochimetaru 4/22/2022 7:23 AM
struct User { var points: [Int] } こういう状況のとき。someは使えない。
Avatar
ただなんか、anyとsomeの境界は、はやい段階で超えるんじゃないかという気はする
7:24 AM
これはArrayの必要がある場面と思います
Avatar
Avatar
omochimetaru
struct User { var points: [Int] } こういう状況のとき。someは使えない。
こういうケースで内部で抽象的な型で取り回したいケースは限定的じゃないかな。
Avatar
そもそもフィールドに置いておく、みたいなのは関数メインのプログラムから見た場合、頻出するシチュエーションではない気がしていて
Avatar
[any Foo] は結構増えそう。
Avatar
omochimetaru 4/22/2022 7:25 AM
関数引数部分の some Sequence は 特殊化が期待できるので [Int] じゃなくて some Sequence<Int> になってもペナルティは無いですね。ちょっとコードの文字数増えるぐらいか。
Avatar
[any Foo] 自体はこれまでもできたけど、 associatedtype があると existential にできなかったようなケースができるようになった(なる)ので。 (edited)
Avatar
structよりも関数に寄せたコードの方が有利な場面が多くなってくる、はありそうだ
Avatar
Avatar
koher
[any Foo] 自体はこれまでもできたけど、 associatedtype があると existential にできなかったようなケースができるようになった(なる)ので。 (edited)
omochimetaru 4/22/2022 7:26 AM
type erasureを手書きしていたケースが any P でタダで使えるのは便利ですね。
Avatar
Avatar
omochimetaru
type erasureを手書きしていたケースが any P でタダで使えるのは便利ですね。
しかも type erasure よりオーバーヘッドも小さかったりしないかな?
Avatar
omochimetaru 4/22/2022 7:28 AM
実装を見てみないとわからないですが、手書きだと二段階ディスパッチになってる部分が、コンパイラサポートなら効率的な実装を生成できそうな気がしますね。
Avatar
Rustの世界観に近づきそう
Avatar
anyキーワード(0335)だけは5.6でもう来てるんですね。 (edited)
Avatar
ですねー。5.7になれば色々入りそうですね。
Avatar
5.6でany付けられる場所洗い出す方法とかないんでしたっけ?
11:26 AM
anyなしに警告が出るのはswift6になったときだったっけ。
Avatar
今のところなさそうですねー(これが最新情報なら) There isn't currently a way to turn on warnings for missing anys in your code. That's intentional; we're working on a lot of generics ergonomics features right now that may change the way programmers update their current use of existential types. https://forums.swift.org/t/finding-existentials-for-any/55956/3 (edited)
There isn't currently a way to turn on warnings for missing anys in your code. That's intentional; we're working on a lot of generics ergonomics features right now that may change the way programmers update their current use of existential types. A lot of Swift code today uses existential types where it doesn't need to because existential types...
👀 1
Avatar
Swift 6モードでコンパイルすればエラーになるみたいなの見た気がするけど、どうやって切り替えるんですっけ?できないのかな?Swift 5か4.2か切り替えるオプションとかありましたよね?
Avatar
omochimetaru 4/22/2022 2:02 PM
コンパイラに対して言語バージョンを指定するオプションがあります
2:03 PM
互換性のない仕様変更があったときは、古いコードはその機能を使ってコンパイルする。
Avatar
ちょっと違いますが、-enable-explicit-existential-typesというフラグがあった頃は、これ使って確認できてたんですよね。 (edited)
Avatar
omochimetaru 4/22/2022 2:10 PM
ほおー
Avatar
Avatar
omochimetaru
互換性のない仕様変更があったときは、古いコードはその機能を使ってコンパイルする。
omochimetaru 4/22/2022 2:10 PM
で、新しいコンパイラで古いバージョンを指定してる場合は、古い書き方に対してコンパイルはできるけど警告が出るので、それを使ってマイグレーションするのが基本。
Avatar
Avatar
omochimetaru
コンパイラに対して言語バージョンを指定するオプションがあります
-swift-version <バージョン番号> というものがそれですか?(私も Swift 6 モードが何者なのか気になってました)
Avatar
Avatar
kebo
-swift-version <バージョン番号> というものがそれですか?(私も Swift 6 モードが何者なのか気になってました)
omochimetaru 4/22/2022 2:57 PM
それだったと思います。
t_thanks 1
2:59 PM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0212-compiler-version-directive.md at main · apple/swift-evolution
2:59 PM
#if compiler ではコンパイラのバージョンがチェックできて
2:59 PM
#if swift ではswiftのバージョンがチェックできます
Avatar
それですね!思い出せなかった。しかし、今のコンパイラでは使えなさそう。
Avatar
omochimetaru 4/22/2022 3:30 PM
Swift --swift-version 3 --swift-version 4 --swift-version 4.2 --swift-version 5 3.0 N/A N/A N/A N/A 3.1 N/A N/A N/A N/A 4.0 3.2 4.0 N/A N/A 4.1 3.3 4.1 N/A N/A 4.2 3.4 4.1.50 4.2 N/A 5.0 3.5 4.1.51 4.3 5.0 5.1 3.6 4.1.52 4.4 5.1
3:30 PM
上のリンク先見る限り使えそうなんだけどなあ
Avatar
😢 $ cat non-any.swift protocol Animal {} struct Cat: Animal {} let animal: Animal = Cat() print(animal) $ $ swift -swift-version 5 non-any.swift Cat() $ $ swift -swift-version 6 non-any.swift <unknown>:0: error: invalid value '6' in '-swift-version 6' <unknown>:0: note: valid arguments to '-swift-version' are '4', '4.2', '5'
3:36 PM
この "Swift 6 language mode" はまだ存在しない架空のモードなのか。
this syntax should be required for existential types under the Swift 6 language mode
https://github.com/apple/swift-evolution/blob/main/proposals/0335-existential-any.md
Avatar
Avatar
koher
この "Swift 6 language mode" はまだ存在しない架空のモードなのか。
this syntax should be required for existential types under the Swift 6 language mode
https://github.com/apple/swift-evolution/blob/main/proposals/0335-existential-any.md
https://swiftfiddle.com/zxvu5klsmnd3lljuw5g2cumamu で compiler options に -swift-version 6 を指定したら動きました.nightly だと行けるようです.
SwiftFiddle is an online playground for creating, sharing and embedding Swift fiddles (little Swift programs that run directly in your browser).
👏🏻 1
Avatar
Avatar
kebo
https://swiftfiddle.com/zxvu5klsmnd3lljuw5g2cumamu で compiler options に -swift-version 6 を指定したら動きました.nightly だと行けるようです.
おおお!ありがとうございます。
3:53 PM
@swift-main -swift-version 6 protocol Animal {} struct Cat: Animal {} let animal: Animal = Cat() print(animal)
Avatar
Avatar
koher
@swift-main -swift-version 6 protocol Animal {} struct Cat: Animal {} let animal: Animal = Cat() print(animal)
swiftNightly BOT 4/22/2022 3:53 PM
Cat()
Avatar
あれ?まだ any 必須のチェックは入ってないのかな?
Avatar
↓のPRにこう書いてあるのでwarningは出そうですけどね(まだ限定的なんですかね?) This diagnostic for requiring any on existential types with Self or associated type requirements has already been staged in as a warning. あと、今後は必須になりそうですね。(3時間前くらいにmainには入っているようです) https://github.com/apple/swift/pull/42558 https://github.com/apple/swift/pull/42590 (edited)
Avatar
Swift5.7だとこのケース(any on existential types with associated type requirements)はwarningが出てきました👀 https://github.com/apple/swift/blob/main/test/type/explicit_existential.swift (edited)
👀 1
Avatar
ほんとだ、 associatedtype がある場合だけ any がないと warning 出ますね。でも、 associatedtype の有無と any って無関係ですよね?奇妙な挙動・・・。
Avatar
Swift5.7からSE-0309 Unlock existentials for all protocolsが入ることでPAT問題が解消される結果、existentialが使われる機会が多くなりそうだけど、anyなしで使うとSwift6でanyつけろというエラーが大量に発生しそうだから先に警告(エラー)にしよう、ってことですかね? https://github.com/apple/swift-evolution/blob/main/proposals/0335-existential-any.md#source-compatibility (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
omochimetaru 4/23/2022 1:08 PM
SE-0309 Unlock existentials for all protocols enables more code to be written using existential types. To minimize the amount of new code written that will become invalid in Swift 6, I propose requiring any immediately for protocols with Self and associated type requirements.
(edited)
1:08 PM
この文はそういう話に見えますね
t_desune 1
1:08 PM
1文前の「enables more code ...」がズバリだ。 (edited)
Avatar
omochimetaru 4/28/2022 4:47 PM
Hello, Swift community. The review of SE-0350: Regex Literals begins now and runs through May 10, 2022. This review is part of a collection of proposals for better string processing in Swift. The proposal authors have put together a proposal overview with links to in-progress pitches and reviews. This proposal introduces a literal syntax for t...
4:47 PM
正規表現リテラルの提案
4:47 PM
名前付きキャプチャだとキャプチャ結果の型のタプルにラベルが付くとか
4:47 PM
シャープをつけると文字列みたいにエスケープ不要モードになるとか
4:48 PM
複数行スタイルとか
4:48 PM
便利な機能がついてて良さそう
4:49 PM
既存のスラッシュ演算子との絡みで文法解釈が変わっちゃうケースがあるのは厳しいね、ほぼ踏むことは無さそうだけど
Avatar
omochimetaru 4/28/2022 6:55 PM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0355-regex-syntax-run-time-construction.md at main · apple/swift-evolution
6:56 PM
文法自体は別提案になってる、きちんと書き下されていてえらい
Avatar
omochimetaru 5/11/2022 8:08 AM
Hello, Swift Community. The review of SE-0357: Regex String Processing Algorithms begins now and runs through May 23, 2022. This review is part of a collection of proposals for better string processing in Swift. The proposal authors have put together a proposal overview with links to in-progress pitches and reviews. This proposal builds on th...
8:09 AM
正規表現と文字列のAPIの提案 switch caseとも組み合わせられるのがオシャレだな
👍 2
Avatar
omochimetaru 5/26/2022 5:27 AM
Hello Swift community, The review of SE-0359 "Build-Time Constant Values" begins now and runs through June 6, 2022. 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...
👀 1
👍🏻 1
5:27 AM
コンパイルタイム定数 @const の提案
5:28 AM
以前Swift 4 TFのときにconstexprとして進んでた話なんだけど、 いろいろ巻き戻ってプロポーザルが書き直されてる。著者の一人のXi Geさんは前回のときも関わってた気がする。
Avatar
朝出てましたが、Opaque Result Type、if #availableで型分岐できるようになるみたいですね A function returning an opaque result type is allowed to return values of different concrete types from conditionally available if #available branches without any other dynamic conditions, if and only if, all universally available return statements in its body return a value of the same concrete type T. struct Square { func asRectangle() -> some Shape { if #available(macOS 100, *) { return Rectangle(...) // ⭕️ } return self } } https://forums.swift.org/t/se-0360-opaque-result-types-with-limited-availability/57729 (edited)
Hi everyone. The review of SE-0360, Opaque result types with limited availability, begins now and runs through June 14, 2022. 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 by email or DM. ...
Avatar
これって分岐の分だけ複数のバイナリが吐き出されることになるんでしょうか? func foo(square: Square) -> some Shape { let rectangle = square.rectangle ... return rectangle } とかだと、 foo まで複数生成される?? (edited)
Avatar
PR見ると戻り値の型の部分だけ分かれているように見えますが、どうなんでしょう?? If particular opaque type descriptor has multiple conditionally available underlying types, emit a special type and witness reference accessors that would be called at runtime to determine actual underlying type. https://github.com/apple/swift/pull/42104
If particular opaque type descriptor has multiple conditionally available underlying types, emit a special type and witness reference accessors that would be called at runtime to determine actual u...
Avatar
実行時のオーバーヘッドがあるのか気になりますね。 opaque type はオーバーヘッドが生じないところに価値があると思うので。
1:21 AM
中身まったくわかってないですが、普通の if ではできず Proposal で "without any other dynamic conditions" でないといけないと言っているからには、 "emit a special type and witness reference accessors that would be called at runtime to determine actual underlying type" と言っても実行時に当該箇所で毎回解決されるわけではなく、最初にロードされるときに環境に合わせて型が解決されるとかなんでしょうか。 (edited)
Avatar
先日の #waiwai-swiftc の内容を踏まえると、ORTで使われる真の型はランタイム関数から取得されてその際に実行単位でキャッシュされるので、foo がたくさん生えるわけではなく foo の返り値の型を取得する関数の内部で分岐が起こるだけ(結果はキャッシュされるので1回だけ)、という感じなのではないでしょうか
2:57 AM
同一モジュール内でSpecializeされるときにどうなるかは気になりますね
3:00 AM
今まで同一モジュール内ならORTの真の型が常に見えてたと思うけど、これが入ると同じ関数から複数種類の型が返ってくる不思議関数になりうるので特殊化が難しそう
Avatar
if #がコンパイル時に解決されれば或いは
Avatar
Avatar
Iceman
今まで同一モジュール内ならORTの真の型が常に見えてたと思うけど、これが入ると同じ関数から複数種類の型が返ってくる不思議関数になりうるので特殊化が難しそう
特殊化されずにモジュール跨ぎの時と同じコードが吐かれてました
t_naruhodo 1
Avatar
Avatar
tarunon
if #がコンパイル時に解決されれば或いは
そのとおりで、minimum-deployment-targetを元に #available が消せる場合は特殊化されてました
Avatar
かしこい
Avatar
この特殊化はどの段階で入るんだろうなぁ。SILOptimizerが走らない-emit-silgen でも特殊化されてるように見えるし、SILGenの段階でやってる?
Avatar
omochimetaru 6/1/2022 5:21 AM
同一モジュール同士なら固定される気もしたけど、そのコンパイル済みのコードが様々な実行環境にデプロイされる可能性があるから動的になるのか。
5:22 AM
で、deployment target次第では、デプロイしうる実行環境のバリエーションが無いことが保証できて固定するのね。
Avatar
こっちのPRが何か関係してますか??ここら辺のコメントから何かしてそうだなあと思いまして // Universally available type doesn't have any availability conditions // so it could be serialized into "unique" slot to safe space. // Check whether there are any conditionally available substitutions. // If there are, it means that "unique" we just read is a universally // available substitution. https://github.com/apple/swift/pull/42167 (edited)
Avatar
import Foundation @propertyWrapper struct WrapperValue<Value> { var value: Value init(wrappedValue: Value) { self.value = wrappedValue } var projectedValue: Self { return self } var wrappedValue: Value { get { self.value } set { self.value = newValue } } func printValue() { print(value) } } class Test { static func test() { (0..<100).map { _ in @WrapperValue var value: Bool = false if value { $value.printValue() // .. compile error on 5.7 } } } } Swift 5.6.1 だと大丈夫だけど Swift 5.7(nightly) だととおらない (edited)
Avatar
@swift-main import Foundation @propertyWrapper struct WrapperValue<Value> { var value: Value init(wrappedValue: Value) { self.value = wrappedValue } var projectedValue: Self { return self } var wrappedValue: Value { get { self.value } set { self.value = newValue } } func printValue() { print(value) } } class Test { static func test() { (0..<100).map { _ in @WrapperValue var value: Bool = false if value { $value.printValue() // .. compile error on 5.7 } } } }
Avatar
Avatar
Iceman
@swift-main import Foundation @propertyWrapper struct WrapperValue<Value> { var value: Value init(wrappedValue: Value) { self.value = wrappedValue } var projectedValue: Self { return self } var wrappedValue: Value { get { self.value } set { self.value = newValue } } func printValue() { print(value) } } class Test { static func test() { (0..<100).map { _ in @WrapperValue var value: Bool = false if value { $value.printValue() // .. compile error on 5.7 } } } }
swiftNightly BOT 6/7/2022 8:18 AM
exit status: 1 with stderr:<stdin>:35:9: error: cannot reference invalid declaration '$value' $value.printValue() // .. compile error on 5.7 ^ <stdin>:32:25: note: '$value' declared here @WrapperValue var value: Bool = false ^
Avatar
なんじゃこりゃ
Avatar
あと property wrapper を body で宣言すると一部のコードが型チェックでクラッシュしますね (edited)
8:24 AM
最低の再現コード今頑張って書いてます
8:25 AM
一瞬 if let hoge の新機能導入してぶっ壊れたのかと思いました
Avatar
omochimetaru 6/7/2022 8:27 AM
必ずじゃないんだ。
Avatar
再現できた これはコンパイラがクラッシュします (edited)
8:31 AM
nightlyでも死ぬ
8:31 AM
@swift-main import Foundation @propertyWrapper struct WrapperValue<Value> { var value: Value init(wrappedValue: Value) { self.value = wrappedValue } var projectedValue: Self { return self } var wrappedValue: Value { get { self.value } set { self.value = newValue } } func printValue() { print(value) } } class Test { static func test() { return [0, 1, 2].compactMap { _ in @WrapperValue var value: Bool? = false if value != nil { return false } return value ?? false } } }
Avatar
Avatar
freddi
@swift-main import Foundation @propertyWrapper struct WrapperValue<Value> { var value: Value init(wrappedValue: Value) { self.value = wrappedValue } var projectedValue: Self { return self } var wrappedValue: Value { get { self.value } set { self.value = newValue } } func printValue() { print(value) } } class Test { static func test() { return [0, 1, 2].compactMap { _ in @WrapperValue var value: Bool? = false if value != nil { return false } return value ?? false } } }
swiftNightly BOT 6/7/2022 8:31 AM
exit status: 134 with stderr:Already type-checked UNREACHABLE executed at /home/build-user/swift/lib/Sema/CSGen.cpp:2956! Stack dump: 0. Program arguments: /usr/bin/swift-frontend -frontend -interpret - -disable-objc-interop -new-driver-path /usr/bin/swift-driver -empty-abi-descriptor -resource-dir /usr/lib/swift -module-name main 1. Swift version 5.8-dev (LLVM 278d67f38c6a910, Swift ee312bc1e20eb01) 2. Compiling with the current language version 3. While evaluating request TypeCheckSourceFileRequest(source_file "<stdin>") 4. While evaluating request TypeCheckFunctionBodyRequest(main.(file).Test.test()@<stdin>:30:15) 5. While type-checking statement at [<stdin>:30:22 - line:39:3] RangeText="{ return [0, 1, 2].compactMap { _ in @WrapperValue var value: Bool? = false if value != nil { return false } return value ?? false } " 6. While type-checking statement at [<stdin>:31:5 - line:38:5] RangeText="return [0, 1, 2].compactMap { _ in @WrapperValue var value: Bool? = false if value != nil { return false } return value ?? false " 7. While type-checking expression at [<stdin>:31:12 - line:38:5] RangeText="[0, 1, 2].compactMap { _ in @WrapperValue var value: Bool? = false if value != nil { return false } return value ?? false " Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it): /usr/bin/swift-frontend[0x60fd223] /usr/bin/swift-frontend[0x60faf6e] /usr/bin/swift-frontend[0x60fd5af] /lib/x86_64-linux-gnu/libpthread.so.0(+0x14420)[0x7f00bdc7c420] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0xcb)[0x7f00bd0cb00b] /lib/x86_64-linux-gnu/libc.so.6(abort+0x12b)[0x7f00bd0aa859] /usr/bin/swift-frontend[0x6038061] /usr/bin/swift-frontend[0x1354b99] /usr/bin/swift-frontend[0x134551e] /usr/bin/swift-frontend[0x1ac48d3] /usr/bin/swift-frontend[0x1ac4c17] /usr/bin/swift-frontend[
Avatar
omochimetaru 6/7/2022 8:35 AM
あれ、 $value のドル記号は関係なかっったのか。
Avatar
前者はドル記号の別の問題かなあっておもいます (edited)
Avatar
Feedback 送りました
👍 2
Avatar
https://github.com/apple/swift/issues/59294 bug ticket がいつのまにかissueになってたのでそっちにも記念にやってみた
Describe the bug Property Wrapper make compiler crash in function body. It can be reproduced with below code. import Foundation @propertyWrapper struct WrapperValue&lt;Value&gt; { var value...
3:24 PM
(ただfixされないとつらいのと割とFBは反応が薄いと聞いてるので、リマインダもかねて
Avatar
jiraじゃなくてissueになったのか
Avatar
Kishikawa Katsumi 6/12/2022 3:06 AM
-Xfrontend -disable-availability-checking こんなオプションあったんですね。
Avatar
これは導入されたらうれしいかもしれない。↓が全部いける extension Array where Element == String { ... } extension Array<String> { ... } extension [String] { ... } https://github.com/apple/swift-evolution/blob/main/proposals/0361-bound-generic-extensions.md
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0361-bound-generic-extensions.md at main · apple/swift-evolution
Avatar
わかりやすくなりますね
Avatar
Kishikawa Katsumi 6/22/2022 2:33 AM
これは良い。
Avatar
Array<Animal>でArray<Cat>とArray<Dog>の拡張も考えられるし、ExistentialならArray<any Animal>と整理もできる
2:34 AM
今のタイミングだからこそ良いですね
Avatar
where の使い所がなくなりそうな勢いだ
Avatar
JavaとかScalaにあるようなアンスコプレースホルダーがあれば
Avatar
Type argument listはconcrete typeである必要があるので、こういうのは無理って書いてある。 extension Pair<Int, _> {} // error: Cannot extend a type that contains placeholders よってwhereはこういう場面で使われることにはなりそう。
Avatar
殆ど要らなくなるんじゃないか
Avatar
コメントが前後した感w
Avatar
そう、これが出来るようになるとは書いてなくて
2:49 AM
まあじゃあ…ってとこではある。あっていいじゃん?とは思うのだけど
Avatar
こういうときにとりあえず使えるAny的な何かがほしい
Avatar
AnyはBottomTypeなのでまた話が違うんですよね…ん?
Avatar
omochimetaru 6/22/2022 2:51 AM
Anyはtop typeね
Avatar
any Anyとはならなかったんだっけ
2:51 AM
Topや、すまん
Avatar
omochimetaru 6/22/2022 2:51 AM
any AnyAny 表記になった(というか旧仕様維持された)けど意味は any Any (edited)
Avatar
じゃあ任意のgenericsを意味するAnyは使えないのか
2:52 AM
any AnyとAnyが分けられていれば
2:52 AM
Pair<Int, Any>でよかった
2:52 AM
分けられてないのでダメだね
Avatar
omochimetaru 6/22/2022 2:52 AM
some Any かな・・・
2:53 AM
extension <Wrapped> Array<Optional<Wrapped>> { ... }
2:53 AM
↑これのsome化で
Avatar
extension Pair<Int, some Any> が書けるのだろうか?
Avatar
omochimetaru 6/22/2022 2:53 AM
extension [some Equatable] { ... }
2:53 AM
と書く形が Future Directions に書いてあるよ
Avatar
ほほー
Avatar
おおそこまで読んでなかった。それよさそうね
Avatar
じゃあアンスコプレースホルダーをsome Anyで表現できるね
Avatar
omochimetaru 6/22/2022 2:54 AM
だから任意のパラメータなら some Any になるけど、、 まあわかりづらいなw
2:54 AM
someなのかanyなのかどっちなんだい、みたいになってる (edited)
Avatar
ただでさえsomeとanyでみんな混乱してるのにw
Avatar
制約付きフィールドを埋めることが出来なくなるのは稀に発生するが
2:54 AM
殆どwhereは出て来なくなるな
2:55 AM
some無しで書けるの辞めさせた方がいいかもね
2:55 AM
○ extension Array<some Animal> × extension Array<Animal>
2:55 AM
後者は混乱の元だ
Avatar
omochimetaru 6/22/2022 2:55 AM
extension Array where Element: Equatable { } ↑この形が残るんじゃないかな
Avatar
それが
制約付きフィールドを埋めることが出来なくなるのは稀に発生するが
Avatar
omochimetaru 6/22/2022 2:55 AM
今回三角カッコの中に書けるのはconcrete typeだけでしょう
Avatar
ああ将来的に可能という話ね
Avatar
omochimetaru 6/22/2022 2:56 AM
ああ
Avatar
proposalは未来の話だが、proposalで言及されてない更に未来で考えられる、破綻しない範囲の話
Avatar
omochimetaru 6/22/2022 2:57 AM
最終形まで行くと多分someまたぎたいケースしか残らなそうだ
2:57 AM
extension <T: P> (T, T) { ... }
Avatar
assoctypeに制約付けてる場合とか
2:58 AM
込み入ったヤツだけwhereが入り用になるんだと思う
Avatar
Kishikawa Katsumi 6/30/2022 11:50 AM
Swift Regexを簡単に試せるツールを作りました。 https://swiftregex.com/
Regular Expression Tester with highlighting for Swift Regex. Quickly test and debug your regex and Regex Builder.
👏🏻 2
Avatar
おお〜 色も付いてる
11:50 AM
色分け用の情報はSwift Regex内部から取り出せるんですか?
11:51 AM
マウス乗せると対応が出る!
Avatar
Kishikawa Katsumi 6/30/2022 11:51 AM
ASTができるからそれをみて頑張る。
Avatar
なるほど
Avatar
Kishikawa Katsumi 6/30/2022 11:52 AM
ASTはInternalだからtestable importで実行している。
11:53 AM
Builderとの対応は簡単な対応関係にないのでけっこう間違ってるのをがんばって補正している。ただ今は本当に間違ってることも多いと思う。
11:53 AM
ここで間違ってる、っていうのは単に私の実装の話。
11:53 AM
Swift Regexのすごいところは現在存在する正規表現をすべてサポートしようとしているところ。 まだ実行はできないけどOnigurumaや.NETの超絶便利だけどマニアックな文法とかもParseまではできる。
Avatar
なるほど
11:54 AM
そうか、公式の実装自体にはコンパイラ部分にソース位置との対応情報を残すAPIがない感じか
Avatar
Avatar
Kishikawa Katsumi
Swift Regexのすごいところは現在存在する正規表現をすべてサポートしようとしているところ。 まだ実行はできないけどOnigurumaや.NETの超絶便利だけどマニアックな文法とかもParseまではできる。
4つの正規表現方言のスーパーセットにする目標ウケますよね
Avatar
Kishikawa Katsumi 6/30/2022 11:54 AM
^[^<>]*(((?'Open'<)[^<>]*)+((?'Close-Open'>)[^<>]*)+)*(?(Open)(?!))$ ^ これとか.NETのマニアックな正規表現。
11:55 AM
ParseはできるけどNot implemetedって出ると思う。
11:55 AM
4つの正規表現方言のスーパーセットにする目標ウケますよね
ウケる。でも正規表現はコピー&ペーストで使いたかったりするから最大限機能がサポートされるのはめっちゃいいと思う。
11:56 AM
高機能なエンジンの正規表現を低機能なエンジンで実行するために書き換えるとかかなり無理だし。
11:59 AM
あ、あと Swift Regexが便利なのは { One(.date(.numeric, locale: Locale(identifier: "en_US"), timeZone: .current)) }{ One(.url()) } っていう正規表現を超えたコンポーネントをRegex Builderだったら差し込めるところだけど、残念ながらFoundationに入ってるのでLinuxだと(今のところ?)動かない。
Avatar
RegexComponentが埋め込めるの改めて考えてみるとすごいですね (edited)
12:26 PM
ゲスト言語である正規表現の中にホスト言語で書いたロジックを差し込めるわけか (edited)
Avatar
Kishikawa Katsumi 6/30/2022 12:46 PM
すごいよね。自分で作ることもできるし。一気に最強の正規表現の実行環境となった。
Avatar
omochimetaru 6/30/2022 3:18 PM
3:19 PM
ジェネリクスの型パラメータ名を絵文字の👻にしてるw
3:19 PM
phantom typeにかけたダジャレ・・・
Avatar
Kishikawa Katsumi 7/1/2022 5:59 AM
Swift RegexはCustomStringConvertibleにかぎかっこ「」が使われたりしててそれも賢いなと思った。クオーテーション使ったら区切りか字そのものかわかりづらいし。
Avatar
omochimetaru 7/1/2022 6:00 AM
ほお。日本語カギカッコは、英語圏の人でもカッコだなって直感的に思えるんですか? (edited)
Avatar
Kishikawa Katsumi 7/1/2022 6:01 AM
それはわからない。わからないけど何かで区切っているということはわかるんじゃないか。 Half Quoteなんとかって名前がついてた。
Avatar
omochimetaru 7/1/2022 6:01 AM
たしかに、少なくとも見た目が枠線っぽいか
Avatar
Kishikawa Katsumi 7/1/2022 6:02 AM
halfWidthCornerQuotedだった。かぎかっこという認識がなくてもQuotedっていうのは伝わるってことかな。 extension CustomStringConvertible { @_alwaysEmitIntoClient public var halfWidthCornerQuoted: String { "「\(self)」" } }
Avatar
omochimetaru 7/1/2022 6:02 AM
たしかにhalf width corner だ
Avatar
Kishikawa Katsumi 7/1/2022 6:04 AM
そしてUnicodeにはhalf widthとfull widthのかぎかっこがあるっぽいな。日本語のかぎかっこじゃないのかもしれない。 (edited)
Avatar
U+300C (LEFT CORNER BRACKET) と U+FF62 (HALFWIDTH LEFT CORNER BRACKET) があるのか…
Avatar
Kishikawa Katsumi 7/1/2022 6:09 AM
ね。検索だとどっちも当たるし日本語のかぎかっこだと思ってた。
6:13 AM
かぎかっこもかぎかっこそのものを扱うときは紛らわしいだろと思うけど、カギかっこは上下ペアなのでクオートよりはだいぶわかりやすかった。
Avatar
omochimetaru 7/1/2022 6:13 AM
【重要】 ←日本人のメールでこれよく見る (edited)
Avatar
【至急】
🏃‍♀️ 1
Avatar
⸤⸣ 上下逆もあったw
Avatar
Kishikawa Katsumi 7/1/2022 6:14 AM
墨付きカッコか。これはUnicodeなんていうんだろ。 (edited)
6:15 AM
開閉でカタチが違うカッコは分かりやすいということだな。
Avatar
「⸣ ⸤」
😆 2
Avatar
日本語の半角カナのかぎかっこが HALFWIDTH LEFT CORNER BRACKET になるっぽいですね。
Avatar
omochimetaru 7/2/2022 3:08 PM
そのHALFだったのか
Avatar
Kishikawa Katsumi 7/2/2022 3:14 PM
半角カナ!
3:15 PM
上下反転は縦書きのカギカッコ(上の例を左右入れ替えると⸤⸣となって縦横がおかしいけど形は合ってる )がなんかの勘違いで入ってしまった、のではないかとみてるけどどうだろう。
3:19 PM
(papyrology, epigraphy) Encloses restored writing where the original scribe has written something else erroneously or where text has been lost and the restoration is likely but not certain.
https://en.wiktionary.org/wiki/%E2%B8%A2_%E2%B8%A3 なんか全然違うことが書いてあるな
Avatar
U+2E22 (TOP LEFT HALF BRACKET) と、U+300C (LEFT CORNER BRACKET) と U+FF62 (HALFWIDTH LEFT CORNER BRACKET) があるんですね 😲 ⸢と「と「 → 後ろ2つが日本語のかぎかっこ(全角と半角)
Avatar
Kishikawa Katsumi 7/3/2022 6:12 AM
@kateinoigakukun Deployed SwiftWasm version. https://t.co/f30hlfsVgX You can see that regex can be parsed and executed without network!
😋 1
6:14 AM
kateinoigakukunさんがSwiftWasmで動くバージョンを作ってくれた。 https://swiftregex-pr-16.onrender.com/ こういうタイプのサイトはWasmでブラウザーだけで動かせるとサーバーリソースをまったく気にしなくてよくなるのですごく便利。
Regular Expression Tester with highlighting for Swift Regex. Quickly test and debug your regex and Regex Builder.
👍 1
6:15 AM
今はPRプレビュー機能が使えるからRender使ってるけどGitHub Pagesみたいな静的なホスティングでも動くはず。
Avatar
Avatar
Kishikawa Katsumi
kateinoigakukunさんがSwiftWasmで動くバージョンを作ってくれた。 https://swiftregex-pr-16.onrender.com/ こういうタイプのサイトはWasmでブラウザーだけで動かせるとサーバーリソースをまったく気にしなくてよくなるのですごく便利。
@Kishikawa Katsumi @Yuta Saito コンソールみるとうまく動いてないっぽいエラー出ますね。SafariもChromeも同様でした。こういうものです? (edited)
Avatar
直したはずなんですが、いくつかコミット消えてますね…w
😮 1
4:29 AM
プッシュし直したのでしばらくしたら治るはず‥! 🙏
4:32 AM
このprotocol conformanceが実行時に読めずに壊れる問題は、5.7からSwiftPMで -c release 時にリンク時GCが有効になったのと、lldのGCがgoldに比べて積極的な挙動をすることで起きてる面白いエラーなんですよね。
t_naruhodo 1
Avatar
Kishikawa Katsumi 7/5/2022 5:47 AM
ごめん、masterからrebaseしたときに壊してしまったのかも。
👍 1
Avatar
omochimetaru 7/12/2022 5:20 AM
It's been a while since the last iteration on the Opt-In Reflection metadata proposal, but we've been working with @Joe_Groff, @ctp and @mren on the updated version recently and while finishing the last bits, we would like to get the community's feedback on the new pieces in the proposal. TL;DR Reflectable is a marker protocol now and develope...
5:21 AM
バイナリに埋め込まれるメタデータを減らしてサイズを小さくできるように、
5:21 AM
今は常に全部埋め込まれているリフレクションメタデータを、
5:21 AM
Reflectable プロトコルに準拠する型だけ埋め込むというコンパイルモードを追加する話
5:22 AM
SwiftUIはそのリフレクションメタデータを使うので、 SwiftUI.View プロトコルには親プロトコルとして Reflectable を追加するらしい。
5:22 AM
また、 printdump 関数はそのリフレクションメタデータがなくても簡易な出力は可能らしい。
5:24 AM
「リフレクションメタデータ」はどうやらタイプメタデータの一部らしいので、オプトインモードにおいて消えるものと残るものがあるっぽいけど、そのあたりの詳細をよく知らないのでよくわからないけど。
Avatar
omochimetaru 7/26/2022 3:07 AM
Hello, Swift community! The review of SE-0366: Move Function + "Use After Move" Diagnostic begins now and runs through August 8th, 2022. 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 by e...
3:08 AM
急にmoveが来た
Avatar
Kishikawa Katsumi 7/26/2022 3:39 AM
コンパイラにヒントを与えることでCopy on Writeによるコピーを減らせる可能性がある、ってことでいいのかしら?
Avatar
omochimetaru 7/26/2022 3:39 AM
そうですね。
Avatar
Kishikawa Katsumi 7/26/2022 3:40 AM
アプリを書いてる分には積極的に使うことはなさそうだけどあると良いものな気がする。
3:41 AM
議論は名前や関数形式がイマイチ不評、って感じなのかな。
Avatar
omochimetaru 7/26/2022 3:41 AM
変数から変数にコピーする時や、関数に渡す時に、moveしながら渡すと、retainが生じない var b = move(a) foo(move(b)) (edited)
3:41 AM
あとはmoveの返り値を捨てれば、そこで変数の寿命が終わる _ = move(x)
Avatar
なんで関数形式なんだろう?
Avatar
Kishikawa Katsumi 7/26/2022 3:41 AM
その代わりaとbはそれ以降使えなくなるんですよね?
Avatar
omochimetaru 7/26/2022 3:42 AM
そうです。moveに渡したところで消える。
Avatar
Kishikawa Katsumi 7/26/2022 3:42 AM
finalize(a)の方が、みたいな意見はわかると言えばわかるな
Avatar
Avatar
koher
なんで関数形式なんだろう?
omochimetaru 7/26/2022 3:42 AM
引数がconsumingだからですね。関数で表現できるからです。
Avatar
C++で見慣れてるのでmoveはしっくりきますが、そうでなければ命名はよくわからないかもですね
Avatar
omochimetaru 7/26/2022 3:44 AM
func move<T>(_ x: __consuming T) -> T { return x } これだけなはず・・・ (edited)
Avatar
Kishikawa Katsumi 7/26/2022 3:44 AM
move/copyだからわかるけどcopyというのが出てこないのが分かりにくいのかな
Avatar
なるほど。そうすると自作しても同じってこと?
Avatar
Avatar
koher
なるほど。そうすると自作しても同じってこと?
omochimetaru 7/26/2022 3:45 AM
はい。もしかしたらmove専用の最適化で差がでちゃうかもしれないけど、、意味としては。
3:45 AM
moveにかぎらず、consmingな引数をもつ関数は同じように振る舞う。渡したら変数がそこで死ぬ。
Avatar
__consuming じゃなく __owned になってる? /// This function ends the lifetime of the passed in binding. func move<T>(_ value: __owned T) -> T https://github.com/apple/swift-evolution/blob/main/proposals/0366-move-function.md#detailed-design
Avatar
__consumingはmakeIteratorとかselfを消費するメソッドにつくやつですね
Avatar
omochimetaru 7/26/2022 3:47 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
3:47 AM
そっか、consmingはselfのときで、引数ではownedか
Avatar
move が本質でないなら、先に __owned__consuming の Proposal をやった方が良いのでは・・・。それとも、その部分はまだ議論したいから、とりあえず一番のユースケースとして move を先に入れちゃおうってことなのかな。裏側はともかく、 move の挙動自体は変わらないから。
Avatar
このproposalはmoveに対する診断を追加するという話なのかなぁ。move自体は今でも作れるっぽいですし
Avatar
Avatar
koher
move が本質でないなら、先に __owned__consuming の Proposal をやった方が良いのでは・・・。それとも、その部分はまだ議論したいから、とりあえず一番のユースケースとして move を先に入れちゃおうってことなのかな。裏側はともかく、 move の挙動自体は変わらないから。
omochimetaru 7/26/2022 3:48 AM
そうそう。オーナーシップが入ってないのに一足とびでmoveだけ出てきたから、驚いた。
Avatar
Avatar
Iceman
このproposalはmoveに対する診断を追加するという話なのかなぁ。move自体は今でも作れるっぽいですし
そうそう。現状use after moveが許されてるんですよね
Avatar
Kishikawa Katsumi 7/26/2022 3:49 AM
move()はC++の人はstd::move()と同じで馴染みやすいのかな。Rustはどう書くんだろう?
Avatar
omochimetaru 7/26/2022 3:49 AM
https://github.com/apple/swift/blob/main/docs/OwnershipManifesto.md#move ↑オーナーシップマニフェストにもmoveが出てくる
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
Rustだと何もかかなくてもmoveになりませんでしたっけ
Avatar
Kishikawa Katsumi 7/26/2022 3:49 AM
moveがデフォルトなのか
Avatar
借用のほうを明示するので
Avatar
Avatar
Kishikawa Katsumi
move()はC++の人はstd::move()と同じで馴染みやすいのかな。Rustはどう書くんだろう?
omochimetaru 7/26/2022 3:50 AM
そうですね。std::moveが出発点、これがムーブセマンティクスって概念と一緒に普及したんで、move が一番わかり易いですが
3:50 AM
そういう前提が無いと唐突なのかも
Avatar
Rustはデフォルトがmove、関数キャプチャしながらmoveはmoveキーワードがあった気がする
Avatar
move || よくみる
Avatar
Kishikawa Katsumi 7/26/2022 3:52 AM
関数でいいんじゃないかな。 そしておっしゃる通り __owned__consumingの話をしないと #move()や@move()の方が、みたいな話と議論できなさそう。 (edited)
Avatar
omochimetaru 7/26/2022 3:58 AM
たしかになあ
Avatar
omochimetaru 7/29/2022 1:05 AM
I think the proposal is nice, and particularly appreciate the attention to detail with defer and repopulating an inout after moving from it. I agree with the general concerns above. move isn't a function and breaks composition in weird ways, it is built-in. I think that Xiaodi's suggestion is good, given that operators feel more "built in". ...
1:05 AM
moveのスレッドに面白い意見があった
1:05 AM
ある値を inout 引数に渡す時は & を付けるのと同じように、
1:06 AM
ある値を move に渡す時は、そこで値が破壊される事を示すオペレータを付けるのはどうか let a = foo() let b = move(<-a) ってアイデア。 これにクリスラトナーも賛成意見を書いてる
Avatar
Kishikawa Katsumi 7/29/2022 2:00 AM
いやーわかりにくいんじゃないかな。&が許されてるのは既存の他の言語に同様の昨日であるからで、move()っていうのもC++で馴染んでるから、だし。
Avatar
omochimetaru 7/29/2022 2:00 AM
いや、 & があることによって、
2:01 AM
コードを見た人が、「ここで引数に渡した値が変更されるかもしれない」という事が視覚的に把握しやすいんですよ
2:01 AM
呼び出し先の関数のシグネチャをしらなくてもそこで副作用が起きる事がわかるのがメリット
Avatar
Kishikawa Katsumi 7/29/2022 2:01 AM
ああ、なるほど。そうするとOperator案は一理あるな。
Avatar
omochimetaru 7/29/2022 2:02 AM
& という記号がわかりにくい、という観点では、 foo(a: inout a) みたいに、キーワードでも良かったかもしれませんね。C#みたいに。 (edited)
Avatar
呼び出し側のコードを見るだけで理解できるのは、メリットですね
2:02 AM
await tryもそうだ。
Avatar
omochimetaru 7/29/2022 2:02 AM
moveも同じで、これを採用すると「ここで引数に渡した値の寿命が終了する」というマークが残せて、読むときにわかりやすい。
Avatar
唯一trailing closureのラベルだけわからんこつなってるが
2:03 AM
記号として<-は適切なんだろうか
Avatar
Avatar
tarunon
await tryもそうだ。
omochimetaru 7/29/2022 2:03 AM
そうですね。calleeの特性を、call expressionのところで専用の目印を付けることでわかるようにする。 (edited)
Avatar
Avatar
tarunon
記号として<-は適切なんだろうか
omochimetaru 7/29/2022 2:04 AM
この <- のアイデアは、 let a = foo() let b = move(<-a) を省略して let a = foo() let b <- a って書けるようにするアイデアもセットになってるから、 <- にしたっぽい。
Avatar
なるほど
Avatar
omochimetaru 7/29/2022 2:05 AM
あ、投稿者のアイデアは let b = <- a だった。
Avatar
Kishikawa Katsumi 7/29/2022 2:05 AM
Source Breakingの可能性はないんだろうか。このタイプのOperatorは作れないんだっけ?
Avatar
omochimetaru 7/29/2022 2:05 AM
C++の文脈だと、「右辺値にする」感は出てますよね。左矢印の右側にオペランドが来るから。
Avatar
<-をprefix operatorとして自作は出来ますね
Avatar
Avatar
Kishikawa Katsumi
Source Breakingの可能性はないんだろうか。このタイプのOperatorは作れないんだっけ?
omochimetaru 7/29/2022 2:06 AM
作れるので衝突しそうw
Avatar
Kishikawa Katsumi 7/29/2022 2:06 AM
moveはSwift.move()ってかけることで回避するということだけど。
Avatar
やってる人がどれだけ居るかは解らん
Avatar
Kishikawa Katsumi 7/29/2022 2:06 AM
まあfunc move()よりは全然少ないだろう。
Avatar
<- 見慣れない感じがすごいですね
2:07 AM
-> の逆でしかないけど
Avatar
そういえば <- 、Goのchannelにもありますね
👍 1
Avatar
@swift-5.6.3 @propertyWrapper class FugaWrapper { public var projectedValue: Int { return wrappedValue } public var wrappedValue: Int init(wrappedValue defaultValue: Int) { self.wrappedValue = defaultValue } } class Hoge { @available(*, unavailable) @FugaWrapper() var piyo: Int = 0 } print(Hoge().$piyo) unavailable なプロパティの projectedValue にアクセスできるのって何でなんでしょう? projectedValueもunavailableになりそうなものですが…
Avatar
Avatar
rinsuki
@swift-5.6.3 @propertyWrapper class FugaWrapper { public var projectedValue: Int { return wrappedValue } public var wrappedValue: Int init(wrappedValue defaultValue: Int) { self.wrappedValue = defaultValue } } class Hoge { @available(*, unavailable) @FugaWrapper() var piyo: Int = 0 } print(Hoge().$piyo) unavailable なプロパティの projectedValue にアクセスできるのって何でなんでしょう? projectedValueもunavailableになりそうなものですが…
swift56 BOT 8/1/2022 2:20 AM
0
Avatar
Hello Swift Community, The review of SE-0365 ended on August 1st, 2022. This proposal improves the ergonomics for use of implicit self in closures capturing self weakly. The Language Workgroup has decided to accept the proposal. Feedback on the proposal was mostly positive. Reviewers identified that the proposal text could be clarified furt...
Avatar
omochimetaru 8/9/2022 7:15 AM
これ嬉しいですね
Avatar
というか今は guard let self else { return } って書けるのか
Avatar
omochimetaru 8/9/2022 7:17 AM
if let foo = fooif let foo になるやつでしょ
Avatar
一回も使ったことなかった
Avatar
できるの5.7だからまだですよw
Avatar
まだかw
7:18 AM
もうすっかり入った気になってた
Avatar
omochimetaru 8/16/2022 4:34 AM
Hi everyone. I'd like to revive a pitch from a while back to turn our shared and owned parameter ownership modifiers into an official language feature. During the recent review of SE-0366, for the move operator, the community raised the importance of considering these modifiers, and their naming, as part of the naming of the move operator it...
4:34 AM
オーナーシップ指定をborrowとtakeにしようってスレッド
4:35 AM
ついでにselfについてはborrowing funcとtaking funcはどうかとのこと
4:36 AM
で、moveはやめてtakeにする
4:40 AM
所有権を奪う操作はすでにUnsafePointer系のAPIとか内部のValueWitnessTableで、takeって言葉が使われてるから
4:40 AM
Swift用語としての一貫性もある
Avatar
Kishikawa Katsumi 8/16/2022 4:44 AM
moveより方向が分かりやすくなるのがいいのかしら
Avatar
omochimetaru 8/16/2022 4:45 AM
まずtake引数が導入されることで、takeオペレータはそれと同じだから、という意味でわかりやすくなりますね (edited)
4:45 AM
元々はowned引数とmoveオペレータだったので、この関係は少し難しかったかも。
4:46 AM
moveスレッドには、逆にowned引数なんだからmoveオペレータじゃなくてownオペレータにしたら?という意見も書き込まれてましたね
Avatar
omochimetaru 8/16/2022 7:20 AM
Hello, Swift community! The review for SE-0366: Move Operation + “Use After Move” Diagnostic ended on August 8th. The Language Workgroup decided that the proposal is returned for revision. Based on early review feedback, the proposal authors revised the syntax of the move(_:) function to a contextual move keyword. The Language Workgroup agrees...
7:20 AM
moveの審査が再検討に差し戻されました。さっきのborrow/takeの検討と連動してそう。 (edited)
Avatar
Avatar
koher
これリンクミスってませんか?
omochimetaru 8/16/2022 8:16 AM
直しました
🙏 1
Avatar
omochimetaru 8/22/2022 5:39 PM
Hello Swift Community, SwiftSyntax is a SwiftPM package that allows one to parse Swift source code into a syntax tree, manipulate that tree, and render the tree back to source code. It is used by tools such as SwiftLint and swift-format that operate on Swift source code. The parsing capabilities of SwiftSyntax (in the module SwiftSyntaxParser) ...
👀 1
👍 1
5:39 PM
Swift ParserのSwift実装だって!
5:39 PM
SwiftSyntaxがlibISSPに依存しなくてよくなる
Avatar
これは嬉しい
5:51 PM
Efficient: The parser should provide similar parsing performance to the existing C++ parser implementation that it seeks to replace.
これがどこまでいけるか気になるな 実装も今後見ていこう
Avatar
なんか昔パフォーマンス出なくてswift-syntaxの統合諦めたみたいな話なかったでしたっけ
Avatar
omochimetaru 8/22/2022 5:53 PM
あったけど、あれはC++でAST作ってそれをSwiftとブリッジしようとしたオーバーヘッドが無視できなかったって事じゃないんかな
5:54 PM
パーサもSwiftだったらそこはアーキテクチャ的な無駄がなくなっていけるんじゃないか
Avatar
C++ のコンパイラパイプラインに C++ の libSyntax を統合しようとして諦めた件かな? https://github.com/apple/swift/pull/27675 これは SwiftSyntax は関係なくて、C++パーサ内での諸々のオーバーヘッドによって満足できるパフォーマンスが出なかったです。
Avatar
omochimetaru 8/22/2022 5:57 PM
Swift側は関係ないか。
Avatar
ああ、それですそれです。
5:57 PM
なるほどー
Avatar
まあ SwiftSyntax はそれ以上に重かったんですけど、いろんなテクニックを駆使してなんとかします笑
Avatar
omochimetaru 8/22/2022 5:59 PM
今回はパーサごと作り直しだからそこはクリアできそうってことですね
Avatar
んー、いちばん重いのはオブジェクトの作成(malloc/dealloc)とリファレンスカウンティング(retain/release)なんですよね。
Avatar
omochimetaru 8/22/2022 6:02 PM
むむ
6:02 PM
新しい ParserもSwiftSyntaxTokenだから (edited)
Avatar
おー、やっぱりそうなんですね。なんかSyntaxArenaとかそれっぽいワードが。
Avatar
omochimetaru 8/22/2022 6:02 PM
RawTokenでそれやるのは同じ・・・?
Avatar
なんで Bump pointer allocation https://github.com/apple/swift-syntax/pull/544
Introduce SyntaxArena that manages the memory of RawSyntax RawSyntaxData is the "data" of raw syntax managed by SyntaxArena, and it has Unowned pointer to the SyntaxArena Tagged union of...
Avatar
omochimetaru 8/22/2022 6:03 PM
マジ
6:03 PM
あつい
6:03 PM
手動メモリ管理Swiftだ
Avatar
めっちゃ最近のPRだ
Avatar
omochimetaru 8/22/2022 6:05 PM
struct RawSyntax { /// Pointer to the actual data which resides in a SyntaxArena. var pointer: UnsafePointer<RawSyntaxData> init(pointer: UnsafePointer<RawSyntaxData>) { self.pointer = pointer } なるほど
6:06 PM
理論上できるよなと思ってたけど本気でやったコード初めて見た
Avatar
そんなに大量のオブジェクトを作る必要のあるプロジェクトもなかなか無いですよね
Avatar
omochimetaru 8/22/2022 6:10 PM
Root SyntaxData now owns the SyntaxArena of the root RawSyntax.
ふむふむ
6:12 PM
SwiftSyntaxのライブラリユーザのコードで、ルートだけ解放しちゃって子供ノードだけ掴んでる状態にするとクラッシュ? (edited)
Avatar
子は親を retain しているので、大丈夫です
Avatar
omochimetaru 8/22/2022 6:14 PM
public struct SyntaxNode { let absoluteRaw: AbsoluteRawSyntax let parents: ArraySlice<AbsoluteRawSyntax> ↑これですか?
Avatar
これですね https://github.com/apple/swift-syntax/blob/1313c36fbf86215d4d6894b8d5e85f1230f013d1/Sources/SwiftSyntax/SyntaxData.swift#L217-L223 private enum ParentOrArena { // For non-root nodes. case parent(SyntaxBox) // For root node. case arena(SyntaxArena) } private let parentOrArena: ParentOrArena (edited)
Avatar
omochimetaru 8/22/2022 6:16 PM
SyntaxBoxなるほど
Avatar
このPRも参考にどうぞー https://github.com/apple/swift-syntax/pull/512
🙏 2
Avatar
omochimetaru 8/22/2022 6:17 PM
子から親をretainするツリーって珍しいですね
6:18 PM
SwiftSyntaxだと出来上がったツリーに部分的にノードを挿入/離脱したりできなくて、 編集する場合まるごと作り直すイミュータブルデータ構造っぽいやつだからそれでいけるのか・・・? (edited)
Avatar
Roslyn の red-green ツリー系統のツリーはそんな感じだと思います
Avatar
omochimetaru 8/22/2022 6:19 PM
へえ〜〜
6:20 PM
これはいろいろ読んだら面白そうだ
Avatar
red-greenツリーってRoslyn由来なんだ 👀
Avatar
omochimetaru 8/22/2022 6:41 PM
We decided early in the Roslyn design process that the primary data structure that developers would use when analyzing code via Roslyn is the syntax tree. And thus one of the hardest parts of the e…
6:43 PM
これが原典かな? イミュータブルなAPIの皮がred treeで、内側の実装ツリーがgreen treeと呼ぶのね
Avatar
ですです。
Avatar
Kishikawa Katsumi 8/23/2022 12:05 AM
Swift Parserはいいですね😍
Avatar
リカバリー能力は既存のSwiftSyntax パーサーより良いと思うので、機会があったら Swift AST Explorer で使ってみていただけると 🙏
Avatar
リカバリー気になる
Avatar
Kishikawa Katsumi 8/23/2022 12:12 AM
使ってみたい。SwiftRegex.comでもBuilderの実行のために使ってるんですけどmain x mainだとバージョン合わせが大変でそこが解消されると嬉しい。
Avatar
omochimetaru 8/23/2022 1:02 AM
@_spi(RawSyntax) public struct RawSyntax { var rawData: RawSyntaxData { unsafeAddress { pointer } }
1:02 AM
謎の文法がある
1:02 AM
/// This is an address-family accessor: a function that is called when /// a value is loaded from the storage, like a getter, but which works /// by returning a pointer to an immutable value of the storage type. /// This kind of accessor also has an addressor kind. /// /// Addressors are a way of proving more efficient access to storage /// when it is already stored in memory (but not as a stored member /// of the type). IMMUTABLE_ADDRESSOR(Address, unsafeAddress) https://github.com/apple/swift/blob/7123d2614b5f222d03b3762cb110d27a9dd98e24/include/swift/AST/AccessorKinds.def
1:03 AM
get とか _read みたいなプロパティ実装方法の一つらしい
1:08 AM
@_spi(RawSyntax) public struct RawTryExprSyntax: RawExprSyntaxNodeProtocol { public var unexpectedBeforeTryKeyword: RawUnexpectedNodesSyntax? { layoutView.children[0].map(RawUnexpectedNodesSyntax.init(raw:)) } public var tryKeyword: RawTokenSyntax { layoutView.children[1].map(RawTokenSyntax.init(raw:))! } public var unexpectedBetweenTryKeywordAndQuestionOrExclamationMark: RawUnexpectedNodesSyntax? { layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) } public var questionOrExclamationMark: RawTokenSyntax? { layoutView.children[3].map(RawTokenSyntax.init(raw:)) } public var unexpectedBetweenQuestionOrExclamationMarkAndExpression: RawUnexpectedNodesSyntax? { layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) } public var expression: RawExprSyntax { layoutView.children[5].map(RawExprSyntax.init(raw:))! } } unexpectedなんちゃらを含む構造で正規の文法よりゆるいソースコードをパースしたそうな雰囲気
1:11 AM
struct ParsedToken { var tokenKind: RawTokenKind /// Whole text of this token including leading/trailing trivia. var wholeText: SyntaxText /// Range of the actual token’s text. /// /// Text in `wholeText` before `textRange.lowerBound` is leading trivia and /// after `textRange.upperBound` is trailing trivia. var textRange: Range<SyntaxText.Index> } leading trivia, token, trailing triviaの持ち方も軽そうな感じになってる
Avatar
SyntaxText も non-owning なテキスト実装として面白いと思いますよ。
Avatar
omochimetaru 8/23/2022 1:31 AM
見てきました。これも良いですね。 public struct SyntaxText { var buffer: UnsafeBufferPointer<UInt8> 実装でも UnsafeBufferPointerの機能もうまく使われてる
1:32 AM
Swift.Substring が機能的に近いと思うけど、不正なUTF-8バイト列を含むソースコードファイルもbyte-to-byteエディットしようとしてるから、Swift.String 系だとダメそうだ
1:33 AM
for case let node? in layoutBuffer { byteLength += node.byteLength descendantCount += node.totalNodes recursiveFlags.insert(node.recursiveFlags) arena.addChild(node.arenaReference) } ↑これ知らんかった
Avatar
omochimetaru 8/23/2022 1:54 AM
元は素直にC++と同じで StringRef 命名だったんだ
Avatar
そーなんですよね。僕はC++コンパイラにコントリビュートしてた人がわかりやすいからStringRefでいいと思ったんですけど。
Avatar
omochimetaru 8/23/2022 2:01 AM
なるほど
2:04 AM
AbsoluteSyntaxPositionはutf-8 offsetしか持ってないけど行番号は SourceLocationConverter で先に行分割結果をキャッシュしといて二分探索なるほどなあ (edited)
Avatar
omochimetaru 8/23/2022 2:43 AM
お〜 TokenPrecedence 面白いアイデア
2:45 AM
これなら一個ずれてもグチャァってならずにそれっぽいアンカーを当てはめられそうだ
2:46 AM
Swiftのディクショナリリテラルが [:] カッコで良かった
Avatar
omochimetaru 8/23/2022 2:53 AM
で、これがトークン読み取る時の一般挙動として実装してあるから文法の実装から隠蔽できるのか
Avatar
Swift向けLLVMバインディングも始まってる https://github.com/apple/swift-llvm-bindings
Swift Bindings for LLVM Project APIs. Contribute to apple/swift-llvm-bindings development by creating an account on GitHub.
Avatar
omochimetaru 8/23/2022 8:17 AM
すごい
Avatar
C++ interopの成果凄すぎる
Avatar
omochimetaru 8/23/2022 8:17 AM
LLVMってC++のテンプレートテクニックかなりヤバいレベルだけど
8:17 AM
いけるんだ。
Avatar
すごすぎる
Avatar
まだガッツリ実装があるわけではなさそう?だけど、StringRefがそのまま使えてる https://github.com/apple/swift-llvm-bindings/blob/llvm.org%2Fmain/Sources/LLVM/LLVM_Utils.swift
Avatar
omochimetaru 8/23/2022 8:19 AM
add_library(LLVM_Utils LLVM_Utils.swift) target_compile_options(LLVM_Utils PUBLIC "-enable-library-evolution" "-emit-module-interface" "-Xfrontend" "-enable-experimental-cxx-interop") target_include_directories(LLVM_Utils PUBLIC "${LLVM_MAIN_INCLUDE_DIR}" "${LLVM_INCLUDE_DIR}")
8:19 AM
実装はこれだけなんじゃない?
8:19 AM
LLVM側はそのまま使うから
Avatar
あー、そっか
Avatar
omochimetaru 8/23/2022 8:20 AM
extension llvm.Twine: ExpressibleByStringLiteral { public init(stringLiteral value: String) { self.init(value) } } こういうSwiftらしく使える部分は付け足していくのかもだけど。
Avatar
LLVMのADT周りさえそのまま使えれば機械的にC++ -> Swiftの書き換えできるのかなぁ (edited)
Avatar
Swift 5.7 is now available! This release contains many of the enhancements announced at WWDC22, including improved generics syntax, regular expression literals, enhanced data race safety, and more. https://t.co/BJpSyLgSPw
Likes
302
Retweets
110
swift 5
Avatar
omochimetaru 9/15/2022 6:07 AM
This supports generic enums, including getting a generic associated value. The one thing that&#39;s not supported yet is the construction of generic enum values. This will allow Optional to be ...
6:07 AM
C++ Interopで、Swiftで定義したenum (associated value付き) を C++から使えるようになってる
6:07 AM
テストコード見るとわかるけど、
6:08 AM
this ポインタから value witness table取り出してそれを使うコードが C++コードとして生成されてて面白い
6:08 AM
LLVM-IRの形で見たやつだ・・・ってなる
Avatar
実行時にVWT経由するのはジェネリックな型だから?
Avatar
omochimetaru 9/15/2022 6:09 AM
そうだと思う PRもgeneric enum support ってタイトルになってるし (edited)
6:10 AM
c++ // CHECK-NEXT: template<class T_0_0> // CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0> // CHECK-NEXT: inline T_0_0 GenericOpt<T_0_0>::getSome() const { // CHECK-NEXT: if (!isSome()) abort(); // CHECK-NEXT: alignas(GenericOpt) unsigned char buffer[sizeof(GenericOpt)]; // CHECK-NEXT: auto *thisCopy = new(buffer) GenericOpt(*this); // CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData(); // CHECK-NEXT: if constexpr (std::is_base_of<::swift::_impl::RefCountedClass, T_0_0>::value) { // CHECK-NEXT: void *returnValue; // CHECK-NEXT: returnValue = *reinterpret_cast<void **>(payloadFromDestruction); // CHECK-NEXT: return ::swift::_impl::implClassFor<T_0_0>::type::makeRetained(returnValue); // CHECK-NEXT: } else if constexpr (::swift::_impl::isValueType<T_0_0>) { // CHECK-NEXT: return ::swift::_impl::implClassFor<T_0_0>::type::returnNewValue([&](void * _Nonnull returnValue) { // CHECK-NEXT: return ::swift::_impl::implClassFor<T_0_0>::type::initializeWithTake(reinterpret_cast<char * _Nonnull>(returnValue), payloadFromDestruction); // CHECK-NEXT: }); // CHECK-NEXT: } else if constexpr (::swift::_impl::isSwiftBridgedCxxRecord<T_0_0>) { // CHECK-NEXT: abort(); // CHECK-NEXT: } else { // CHECK-NEXT: T_0_0 returnValue; // CHECK-NEXT: memcpy(&returnValue, payloadFromDestruction, sizeof(returnValue)); // CHECK-NEXT: return returnValue; // CHECK-NEXT: } // CHECK-NEXT: }
6:10 AM
↑生成されたコードも constexpr 使って最適化で畳めそうな感じになってる
Avatar
これは面白いなぁ
6:11 AM
IRGenのコードと重複がかなり出そうだけどメンテ頑張るのかな
6:12 AM
いい感じに共有できてる?
Avatar
omochimetaru 9/15/2022 6:12 AM
二重実装に見える
Avatar
すごい
6:13 AM
これからはランタイムライブラリとIRGenとCxxInteropでランタイムデータ構造の整合を取らないといけない
Avatar
omochimetaru 9/15/2022 6:13 AM
C++から使うためにはテンプレートパラメータ+コードの形にexportするしか無いしこうなるよなあ VWTから先の本体?的な処理は共有されるからいいけど
6:15 AM
Swift側にもC++ Interopしたものを扱うための補助ライブラリがあるし (CxxIterator)
6:15 AM
C++側にもSwift exportしたものを扱うための補助ライブラリがあるようだ
Avatar
こうなるんだ c++ /// Swift's Int type. using Int = ptrdiff_t; /// Swift's UInt type. using UInt = size_t;
Avatar
omochimetaru 9/15/2022 6:19 AM
なるほど。std::intptr_t かと思った
6:19 AM
// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast<swift::_impl::ValueWitnessTable **>(metadata._0) - 1;
6:19 AM
ここで使われてる swift::_impl::ValueWitnessTable を探し中 (edited)
Avatar
見当たらない
Avatar
omochimetaru 9/15/2022 6:21 AM
もしかしてRuntime用のヘッダーと共有できてるのかなと思ったんだけど
6:21 AM
そっちは swift::ValueWitnessTable にみえるんだよね
Avatar
そうそう
Avatar
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 9/15/2022 6:23 AM
おわー
6:23 AM
ズタズタに切り刻まれてた。
Avatar
c++ os << "\nstruct ValueWitnessTable {\n" << membersOS.str() << "};\n\n";
6:23 AM
kusa
Avatar
omochimetaru 9/15/2022 6:23 AM
#include "swift/ABI/ValueWitness.def"
6:23 AM
あっ、XMACROだ!
6:23 AM
そういうことか〜
6:25 AM
半分ぐらい共有されてる感じだな・・・
6:26 AM
printPrimitiveGenericTypeTraits で基本型のtraitが生成されてる。 os << "template<>\n"; os << "static inline const constexpr bool isUsableInGenericContext<" << typeInfo.name << "> = true;\n\n";
6:27 AM
おもしろいなあ
Avatar
C++のテンプレートのコード生成、コード生成器が壊れたりサポートしてない入力が来たときにエラーメッセージが大変なことになりそう
6:34 AM
conceptってやつで将来的になんとかなるのかな
Avatar
omochimetaru 9/15/2022 6:40 AM
C++テンプレートコードを自動生成する時の話? C++テンプレートをユーザが使うときの話?
Avatar
そうか、C++テンプレートコードを生成するときはその結果はClangに食わせないから、エラーが出るのはコード生成が終わってそれをユーザが使うときか (edited)
6:42 AM
なのでユーザが自動生成されたテンプレートを使うときに大変かな、という懸念
Avatar
omochimetaru 9/15/2022 6:44 AM
そういう意味では、両方の問題が同時に来るから普通のテンプレートより厳しい状況になりそうだね。
6:45 AM
C++テンプレート一般についていえば
6:45 AM
テンプレートクラスやライブラリの実装者が工夫することで
6:45 AM
わかりやすい壊れ方をするように作ったりはできるよ
Avatar
なるほど
Avatar
omochimetaru 9/15/2022 6:46 AM
iterator_traitsは、イテレータに関する型情報を取得するためのクラスである。
6:47 AM
traitパターンってのがあって、それで型をプロトコル(?)に準拠させたい側が丁寧にusing(or typedef) しておいて
6:47 AM
みたいにやっておくと、変なもの与えてもtrait準拠の時点でおかしいから
6:47 AM
コード本文の深いところに入る前にエラーが出る
6:48 AM
あと今調べたんだけど頑張ればSFINAEを使って、メンバを持っているかどうかも静的に判定できるらしい
6:48 AM
だからめちゃくちゃ頑張ればconcept準拠相当のロジックを事前にテンプレートプログラミングで判定できるんじゃないかな・・・?
Avatar
へー、そこもチェックできるんだ
6:48 AM
めちゃくちゃ頑張れば。。
6:48 AM
(コンパイル速度を犠牲にして)
Avatar
omochimetaru 9/15/2022 6:48 AM
concept文法が入るとそのへんがパターンとして簡単にかけて便利。
Avatar
Avatar
Yuta Saito
(コンパイル速度を犠牲にして)
omochimetaru 9/15/2022 6:49 AM
その犠牲は確かに・・・
6:49 AM
さっきの isUsableInGenericContext も traitパターンになってると思う なにをtraitパターンと言うか正確にわかってないけど・・・ パラメータ特殊化を使ってboolを返すようにしてconstexprで評価できるようにしている
Avatar
なるほどなぁ。
Avatar
omochimetaru 9/15/2022 6:52 AM
CHECK-NEXT: template<class T_0_0> // CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0> // CHECK-NEXT: inline bool GenericOpt<T_0_0>::isNone() const { // CHECK-NEXT: return *this == GenericOpt<T_0_0>::none; // CHECK-NEXT: }
6:52 AM
てかここのrequiresってconceptか?
Avatar
マクロよりはマシかなぁ
6:52 AM
Avatar
omochimetaru 9/15/2022 6:52 AM
C++20から導入される「コンセプト (concepts)」は、テンプレートパラメータを制約する機能である。この機能を使用することで、以下のような面でプログラミングのしやすさが向上する:
6:52 AM
もう使ってそう
Avatar
ぽい
6:52 AM
すごーい
Avatar
omochimetaru 9/15/2022 6:53 AM
c++ // 描画可能コンセプト。 // メンバ関数draw()を持つことを要求する template <class T> concept Drawable = requires (T& x) { x.draw(); // 型Tに要求する操作をセミコロン区切りで列挙する。 // ここでは、メンバ関数draw()を呼び出せることを要求している。 };
6:53 AM
結局こんな文法になったのか。
6:54 AM
なんか直接的で受けるな。Goのgenericsもこんな感じの仕様が検討されてたのを昔見た。どうなったんだろ。
Avatar
requires節は関数本体に書いてたstatic_assertが関数宣言部にかけるようになった感じ? c++ template <class T> requires std::constructible_from<T, int> && std::move_constructible<T> T make_from_int(int x) { return T(x); } (edited)
Avatar
omochimetaru 9/15/2022 6:57 AM
static_assertは宣言にも書けた c++ template <class T, std::size_t N> struct X { static_assert(N > 0, "number of array elements must greater than 0"); T array[N]; }; けど関数とペアにする場合たしかに本文か?
6:58 AM
そんな解釈で良さそうに思える
Avatar
ふむふむ
6:59 AM
つまりSwiftコンパイラから生成されたヘッダを読み込むにはC++20が必須
Avatar
omochimetaru 9/15/2022 6:59 AM
C++11の会議において「コンセプトは本当にC++11に入れるんだな?」という投票を行い、コンセプトをC++11に入れる合意が得られてコンセプトが入った規格案であるCommittee Draft (CD) が公開された。しかしその後、コンセプトはやはり使うのが難しく複雑だということで取り下げられ、コンセプトが取り除かれたCommittee Draft (CD2) が再度公開された。ただしその際、コンセプトの策定で培った経験は活かすことになり、整理された自然言語としてテンプレートパラメータへの要求が規格に載ることとなった。 C++14の策定において、コンセプトの複雑さを回避して必要最小限の機能のみをまとめた「軽量コンセプト (Concept Lite)」という機能を入れることが計画された。これは、C++11で導入されたconstexprを使用し、bool型の定数式として制約を定義し、requires節にbool型定数式を指定して制約するというものだった。これはConcept TS (Technical Specification) として個別に各国承認が行われ、遅延したがC++17に導入される予定だった。 軽量コンセプトとしてなるべく早くプログラマにこの機能を導入するつもりだったが、その後コンセプトをさらに仕様拡張としていくことを考えると、最初の設計から大幅に違ったものになってしまう懸念があった。また、コンセプトは標準ライブラリの仕様に適用すべきものであるため、より完全なものが求められた。そのため、軽量コンセプトという予定はなくなり、より時間をかけて完全なコンセプトの仕様を策定することとなり、C++20で導入されることとなった。
7:00 AM
めちゃめちゃ迷走してたんだな
Avatar
完全なコンセプトがようやく完成したのか
Avatar
Avatar
Yuta Saito
つまりSwiftコンパイラから生成されたヘッダを読み込むにはC++20が必須
omochimetaru 9/15/2022 7:01 AM
どうだろう、検査を足してるだけだから、それを剥がせば許容バージョンを下げられそうだけど
Avatar
インスタンス化できるべきでないテンプレートがインスタンス化されてしまう可能性があるくらい?
7:03 AM
C++ Language And Library Requirements Importing Swift APIs into C++ requires certain C++ features introduced in newer C++ language standards. The following C++ standards are expected to work: C++20. It is the recommended standard, as C++ 20 concepts enable type checking for imported Swift generic APIs. C++17 and C++14 are supported with some restrictions. Some generic APIs might not be available prior to C++20.
7:03 AM
14まで下げられるって。
Avatar
書いてあった
Avatar
omochimetaru 9/15/2022 7:04 AM
ドキュメントいろいろ増えてる
Avatar
Kishikawa Katsumi 9/18/2022 3:36 PM
WKWebViewにこういうシグネチャのメソッドがあって、 func evaluateJavaScript( _ javaScript: String, in frame: WKFrameInfo? = nil, in contentWorld: WKContentWorld, completionHandler: ((Result<Any, Error>) -> Void)? = nil ) こんなふうに使うんだけど webView.evaluateJavaScript("document.body.innerHTML", in: nil, in: WKContentWorld.defaultClient) 2番目と3番目の引数のラベルがどちらも in で、2番目のラベルはデフォルト引数が設定されているので省略可能なのだけど、 webView.evaluateJavaScript("document.body.innerHTML", in: WKContentWorld.defaultClient) こういうふうに省略して書くと Extra argument 'in' in call とか、 completionHandler を付けても Cannot convert value of type 'WKContentWorld' to expected argument type 'WKFrameInfo?' ってコンパイルエラーになるんだけど、これは引数ラベルを同じにしてしまったことが問題なのかしら?
Avatar
同じかつ両方省略可能にしたことによるバグっぽいですね
Avatar
Kishikawa Katsumi 9/18/2022 6:27 PM
バグっぽいですよねえ。コンパイラの方のバグ、ってことですよね?
Avatar
仕様バグかなぁ
6:33 PM
優先度が何かしら決まればエラーじゃなくは出来るから
6:33 PM
優先度がないことがバグ?と言えばそうかも
Avatar
Kishikawa Katsumi 9/18/2022 6:37 PM
見つけたからレポートしてみよう。 AppleのAPIで見つかるのがおもしろいですよね。
Avatar
omochimetaru 9/19/2022 8:16 AM
その辺のラベルマッチングは結構実装読んだけど、探索的な動作はしないから無理なんですよね
8:19 AM
ただa:b: にたいして b:a: で呼び出すみたいな前後入れ替えとかは診断出すために対応を調べていたりして
8:19 AM
ややこしい動作も持っていたりする
8:19 AM
ラベルマッチングに関する文書は存在しなくて実装が仕様状態なんで、
8:20 AM
仕様のバグなのかどうかもハッキリしない
Avatar
Kishikawa Katsumi 9/19/2022 8:29 AM
この例だと順序と型で区別できそうですけど無理ですか?
Avatar
omochimetaru 9/19/2022 8:30 AM
型での区別はやらない事になっているんですよね 末尾クロージャーだけちょっと特殊な型の考慮があったりするんですけど
8:30 AM
理由?というかアーキテクチャとしては
Avatar
Kishikawa Katsumi 9/19/2022 8:31 AM
型見ないんだ。そうすると型のオーバーロードはどうなるんですか?
Avatar
omochimetaru 9/19/2022 8:31 AM
オーバーロードの候補解決と型推論が関係していて
8:31 AM
「どのオーバーロードを呼び出すか」っていう選択肢は型推論システムに対して提供されるんですけど
8:32 AM
「あるオーバーロードを呼び出す時に引数のラベルマッチングをどうするか」っていう選択肢は提供されなくて、 型推論システムにとっては、どのオーバーロードを呼び出すかを考える時点でラベルマッチングは固定済みなんですよね
8:34 AM
8:34 AM
今回は in: ラベルで重複していますけど
8:34 AM
もっと一般的な問題としてはラベル無しの場合を考えるとよくて、(ラベル無しはラベル文字列が "" の場合として同じ理屈になる)
Avatar
Kishikawa Katsumi 9/19/2022 8:34 AM
これが解決できないんですねえ。
Avatar
omochimetaru 9/19/2022 8:35 AM
↑の例みたいにデフォルト引数をそれぞれ与えてしまえば、 もし型を考えるなら、2通りの型チェックで呼び出せる事になる 今はそうなっていない
8:35 AM
もし解決できるようにすると、
8:35 AM
与えられてる実引数がどのパラメータに対応するかを、 この方式で引数を増やせば増やすほど候補が増えていくので
8:35 AM
例えば4引数とかにしちゃったら探索範囲が2^4で16倍に爆発しちゃいます
8:35 AM
具体的な型がわかっているときならすぐにチェックできるけど
8:36 AM
型推論の最中だったりすると型が未確定のままこの組み合わせを調べないといけないとかが生じるので
8:36 AM
オーバーロード数が増えてるのと同じで型推論がめっちゃ重くなっちゃう状況が発生する可能性があります
Avatar
Kishikawa Katsumi 9/19/2022 8:40 AM
そうなんですね。コンパイルエラーにしないのはできるかもしれないけど、そうすると型推論などのそれ以前の処理に大きく影響する恐れがあると。
Avatar
omochimetaru 9/19/2022 8:42 AM
そうですね
8:43 AM
あと、ラベルマッチングは末尾クロージャの扱いとか、可変長引数の扱いとかの仕様もあるので、結構複雑で、 既存実装を型推論エンジンの中で問題として解かせるようにする改修の実装が大変そうです。
8:46 AM
末尾クロージャは、渡す引数のクロージャにはラベルがついてないけど、 受け取る関数側にはラベルが付いているので、マッチングルールが例外処理されていてややこしくて、 そこに複数末尾クロージャの仕様が入って問題が発生したので SE-0286 で仕様が直された事があります (edited)
8:46 AM
ラベルマッチングの仕様がそもそも文書化されていないのに、 ここだけ急に仕様変更が形式的な審査手順を踏んだのでなんか妙な感じでした。
8:47 AM
変更前後で互換性問題が生じるのでまあ適切ですけど。
Avatar
Kishikawa Katsumi 9/19/2022 8:52 AM
つまりWebViewのこのAPIは近い将来ではコンパイルできるようになる可能性は低い。 コンパイラのバグとも言えない(仕様が決まってない)。 ということはWebViewのこのメソッドシグネチャが悪いって感じだけどもうPublicになってるからそれはそれで難しそうだな。
Avatar
omochimetaru 9/19/2022 8:53 AM
簡単な?対策としては
8:53 AM
extension WKWebView { func evaluateJavaScript( _ javaScript: String, in contentWorld: WKContentWorld, completionHandler: ((Result<Any, Error>) -> Void)? = nil ) }
8:53 AM
これを自前で定義すれば呼び出せるかもしれません
8:53 AM
デフォルト引数を与えるんじゃなくて、引数が無いバージョンをオーバーロードする。
8:54 AM
たしか「あるオーバーロードと共にデフォルト引数を使う」より、「最初から引数がないオーバーロードを選ぶ」ほうがコストが安いっていうロジックが入っている (edited)
Avatar
Kishikawa Katsumi 9/19/2022 8:55 AM
ああ、なるほどね。今はXcodeの補完に差はないけど、昔は補完をうまくするためにデフォルト引数じゃなくてオーバーロードで、みたいなのを思い出した。
8:56 AM
そうするとWKWebViewの方で、デフォルト引数じゃなくて引数の数でオーバーロードにする、という修正で解決できる?
Avatar
Avatar
Kishikawa Katsumi
そうするとWKWebViewの方で、デフォルト引数じゃなくて引数の数でオーバーロードにする、という修正で解決できる?
omochimetaru 9/19/2022 8:56 AM
たしかに。バグレポート出したらそういう修正が降ってくる可能性はありますね。
Avatar
Swift Platform Work Group (tentatively named) is a new Swift community workgroup, working together to improve platform usability of Swift. This includes: Expanding available target platforms for Swift. SPWG should embrace community works in cross compilation area, and, help the community to contribute related changes to upstream. So far, the ...
11:54 PM
Swift Platform WGというのが発足したらしい いろんな環境のサポートを進めていくそうだ
11:55 PM
↑WASM代表で最近Appleに転職したMaxさんの名前がフォーラム投稿に書かれている (edited)
11:55 PM
AppleがWASM対応に本気だしたかもしれない (edited)
11:56 PM
そういえば、Swiftコンパイラの部分的なセルフホストが始まってるから、
11:57 PM
全く新しいプラットフォームに対応する難易度が上がるな。
11:57 PM
C++だけでビルドできる古いSwiftをまずポーティングして、 その次にその古いSwiftを使って最新のSwiftがビルドできる、 というブートストラップになるはず?
Avatar
Avatar
omochimetaru
AppleがWASM対応に本気だしたかもしれない (edited)
Note that this initiative is not from the Swift core team or Apple. As the original author, I’m calling out for community effort and official support in this area by forming SPWG officially.
一応
Avatar
う~む
10:26 AM
As a contributor, I observed noticeably slow responses to patches around platforms apart from Darwin and Linux, even for trivial ones. This could be a result of multiple factors: new platform maintainers often don’t have commit access; there’s no platform manager so non-trivial changes are not easily evaluated; there’s no CI or testing infrast...
10:27 AM
ここで、karlさんのWASMって結構できてるけどこれ以上何するの?って質問に答えてるけど、
10:28 AM
コミュニティエフォートでどうにかならない話をしてるような・・・
10:29 AM
でも stevapple さんはGitHubみるとAppleじゃなくて中国の大学生なのか。appleついてるだけか。
Avatar
はい
Avatar
アプリ開発初心者です。Swiftの学習で行き詰まっておりまして、お時間ある方にご教授願いたいです。 viewControllrで画面を追加して 追加した画面にTable view及び Table viewcellをドラッグアンドドロップし、シュミレーターで確認すると シュミレーター画面が飛び、 @mainに赤線が引かれ Table view:numberOfRowsinSection: unrecognized Serector sent to instance というエラーが出てしまいます。 わかる方いたらぜひ教えてくださるとありがたいです。
Avatar
Kishikawa Katsumi 9/28/2022 7:46 AM
エラーの直接の原因は、numberOfRowsinSection:というTable Viewにデータを何件表示するか、ということを示す関数がないことですが、そこを直しても今度はTable Viewに表示する内容を示す関数がないエラーが出る、、、となると思います。 何か参考にされて書かれてますか?そうだとすると手順をいくつか飛ばしてしまってると思います。 参考にされてるものがあるとするとその内容を載せてもらえますか?
Avatar
ご回答頂きありがとうございます。 とても助かります。 YouTubeの Rikuto Satoさんの iPhoneアプリ開発講座2時間で マスター 総集編のパート8 リストを使ったアプリを参考にしながらやっております
Avatar
Kishikawa Katsumi 9/28/2022 2:09 PM
おそらく、説明のテーブルビューをドラッグ&ドロップで配置したあとに、delegateとdataSourceの線をView Controllerと繋ぐ手順(4分あたり)の後に何もコードを書かずに起動しているのではないでしょうか? delegateとdataSourceの線を繋いだ後はテーブルのデータをどうするか、という関数を書かないとそれが見つからないということでそのようなエラーになります。続けて解説をみていくとコーディングの説明に入ってその見つからない関数を書いていくところが見られます。 (edited)
2:09 PM
全部は見てないですが手順どおりに全くおなじようになぞれば問題はなさそうですよ。 (edited)
Avatar
そうです!動画の主が delegateとdata sauceをview Controllerに繋いでTable viewcellの identifyにcellと入力し、シュミレータで リストの欄ができていたので勘違いしていました! 今一度最初からシュミレータで起動しなくとも一回最後までやってみようと 思います! 丁寧にありがとうございました!! また壁にぶつかったら頼りにくるかもしれないのでその時はまたよろしくお願いします。本当にありがとうございました!!
Avatar
omochimetaru 9/30/2022 4:53 AM
可変長ジェネリクスのパラメーターパックのドラフト https://forums.swift.org/t/pitch-parameter-packs/60543
Hello, Swift community! @Slava_Pestov and I have been working on an updated design for variadic generics in Swift. This pitch details the fundamental concept of abstracting over a list of zero or more type parameters with parameter packs. I've pasted a draft of the design below, and it is also available at swift-evolution/NNNN-parameter-packs.m...
👀 1
Avatar
omochimetaru 9/30/2022 5:07 AM
typealias G<E...> = (Array<E>...)
これ難しいな
Avatar
これは久々の大型マニフェスト? https://gist.github.com/DougGregor/4f3ba5f4eadac474ae62eae836328b71
A possible vision for macros in Swift. GitHub Gist: instantly share code, notes, and snippets.
4:21 AM
Hey all, As Swift evolves, it gains new language features and capabilities. One of the ways in which it grows is via new syntactic sugar to eliminate common boilerplate, taking something that can be written out in long-form and making it more concise. Such features don't technically add any expressive power to the language, because you can alwa...
Avatar
マジか
Avatar
マクロ...
Avatar
おおお
4:27 AM
SwiftSyntaxがSwift化したのもこれの布石だったりするのかな
4:28 AM
今までmacOSでしか使えなかったし
Avatar
なるほど (edited)
Avatar
We propose to introduce a macro system into Swift. At a very high level, macros can be explicitly triggered with syntax such as #stringify(x + y), subsuming a number of existing expressions that use similar syntax already (#line, #colorLiteral(...), etc.) with a general features. Macros can also be triggered more implicitly in response to type checking, e.g., applying a macro to the argument passed to a function. Macro arguments are type-checked so that tooling behaves similarly to today, but macro evaluation involves transforming the syntax so that it can serve a number of different use cases.
4:50 AM
面白そうな事書いてあるな
Avatar
Kishikawa Katsumi 10/18/2022 4:51 AM
これはスッと受け入れられそうな気がする。CodableやPropertyWrapperみたいなより複雑な仕様が既にあるし、という感覚に私はなっている。
Avatar
マクロの入力は自由なテキストではなく、syntaxが縛られていて、マクロ引数が型検査されるとある
4:54 AM
#stringify マクロの実装サンプル (edited)
4:55 AM
SwiftSyntaxの拡張ライブラリであるSwiftSyntaxMacrosパッケージのライブラリを使って 引数としてSwiftSyntaxの MacroExpansionExprSyntax を受け取るんやな (edited)
Avatar
#line の一般化もしてそう
t_desune 1
Avatar
マクロの実装本体を、
5:08 AM
ソースコードの中で書くんじゃなくて
5:09 AM
ライブラリの中でセマンティックなCST変換器として実装するのは
5:09 AM
結構珍しいアプローチな気がする?
Avatar
Rustのproc_macroはちょっと似てる?
Avatar
https://qiita.com/yagince/items/546d86588aaa3fdb3c94 proc_macro crateを使って、TokenStreamの変換関数を書くんだね、似ているな
davidpdrsn/juniper-eager-loading: Library for avoiding N+1 query bugs with Juniper ↑の実装を読んでいて、CustomDeriveってこうやって書くのか...
Avatar
ただしproc_macroはRustとして不正なトークン列も受け付けられる
Avatar
なるほど
5:14 AM
Swiftのアプローチのほうがより堅牢になるのかも?
Avatar
かも
Avatar
macro(contexts: [.expression], external: "MyMacros.Line") var line: Int { get } macro(contexts: [.expression, .parameter], external: "MyMacros.Stringify") func stringify<T>(_ value: T) -> (T, String) マクロの型宣言 らしい
Avatar
externalってなんだろ
Avatar
public struct Stringify: ExpressionMacro, ParameterMacro { public static func apply( arguments: (String?, ExprSyntax)..., in context: MacroEvaluationContext ) -> (ExprSyntax, [Diagnostic]) { let node = arguments[0].1 return (##"(\(node), #"\(node.description)"#)"##, []) } }
6:16 AM
実装の名前
Avatar
おおー、なるほど
Avatar
protocol Cleanup { func cleanup() } macro(contexts: [.statement], external: "MyMacros.LocalCleanup") func localCleanup<Value: Cleanup>(_ varName: String, _ initializer: Value) --- #localCleanup("file", File(opening: "hello.txt")) --- let file = File(opening: "hello.txt") defer { file.cleanup() } (edited)
6:19 AM
defer生み出せるの面白いな。moveonly typeがあれば要らないマクロですが・・・
6:22 AM
// In the standard library extension Equatable { macro(contexts: [.conformance], external: "MyMacros.EquatableSynthesis") static func ==(lhs: Self, rhs: Self) -> Bool } // In the macro definition library struct EquatableSynthesis: ConformanceMacro { public static func apply( conformingType: TypeDecl, protocol: ProtocolDecl, witness: FunctionDeclSyntax, in context: MacroEvaluationContext ) -> (FunctionDeclSyntax, [Diagnostic]) { let comparisons: [ExprSyntax] = conformingType.storedProperties.map { property in "lhs.\(property.name) == rhs.\(property.name)" } let comparisonExpr: ExprSyntax = comparisons.map { $0.description }.joined(separator: " && ") return witness.withBody( """ { return \(comparisonExpr) } """ ) } }
6:22 AM
この TypeDecl は今無いやつだ、めっちゃ欲しい
6:23 AM
無いので自作してるやつ
Avatar
macro の宣言時には今までのようなプレフィックスがつかないんですね
2:39 PM
#macro だと実際に展開される側のものと紛らわしいのでないのは分かるんですが、何となく何かで囲われてないと違和感がある…
Avatar
macro がそのprefixだと思います カッコの中が長いからわかりづらいけど つなげれば macro static func の形になってます
t_naruhodo 1
Avatar
もう使える記号がない
Avatar
@swift-5.6.3 import Foundation enum Key: String, Codable { case a } let data1 = try JSONEncoder().encode([Key.a : 0]) print(String(data: data1, encoding: .utf8)!) let data2 = try JSONEncoder().encode([Key.a.rawValue : 0]) print(String(data: data2, encoding: .utf8)!)
Avatar
Avatar
t.ae
@swift-5.6.3 import Foundation enum Key: String, Codable { case a } let data1 = try JSONEncoder().encode([Key.a : 0]) print(String(data: data1, encoding: .utf8)!) let data2 = try JSONEncoder().encode([Key.a.rawValue : 0]) print(String(data: data2, encoding: .utf8)!)
["a",0] {"a":0}
Avatar
前者はなんで’こうなるんでしょう?
Avatar
@swift-5.6.3 import Foundation enum Key: String, CodingKeyRepresentable, Codable { case a } let data1 = try JSONEncoder().encode([Key.a : 0]) print(String(data: data1, encoding: .utf8)!) let data2 = try JSONEncoder().encode([Key.a.rawValue : 0]) print(String(data: data2, encoding: .utf8)!)
Avatar
Avatar
Iceman
@swift-5.6.3 import Foundation enum Key: String, CodingKeyRepresentable, Codable { case a } let data1 = try JSONEncoder().encode([Key.a : 0]) print(String(data: data1, encoding: .utf8)!) let data2 = try JSONEncoder().encode([Key.a.rawValue : 0]) print(String(data: data2, encoding: .utf8)!)
{"a":0} {"a":0}
Avatar
CodingKeyRepresentable もう使えますよ
Avatar
便利そう
Avatar
みたいですね。名前からぱっと分からなかったんですけどDictionaryのキーのための型なのかな?
8:44 AM
こんな感じで分岐してるんで、Dictionary用といってもいいでしょうね。
Avatar
IntとStringしか辞書にならなかったのが、CodingKeyRepresentableでカスタム可能になったやつか。
Avatar
CodingKeyRepresentable 、 15.4 以降なので微妙に使いづらいんですよね…
😧 1
Avatar
モバイルアプリだともうちょっとかかりそうですね
4:00 PM
Optional<Foo> 形式で書くと = nil によるデフォルト初期化が起きないらしい。
😅 3
Avatar
Avatar
omochimetaru
Optional<Foo> 形式で書くと = nil によるデフォルト初期化が起きないらしい。
今はどうなったのかわからないですが,以前はそれのせいで T? だと二重初期化が起こるみたいな問題があったらしいですね.SwiftNIO とかはそれを避けるために全部 Optional<T> で書き直したりしてました. https://github.com/apple/swift/issues/54184
Previous ID SR-11777 Radar rdar://problem/57156726 Original Reporter @weissi Type Bug Status Resolved Resolution Done Attachment: Download Additional Detail from JIRA Votes 0 Component/s Compiler L...
Avatar
Avatar
kebo
今はどうなったのかわからないですが,以前はそれのせいで T? だと二重初期化が起こるみたいな問題があったらしいですね.SwiftNIO とかはそれを避けるために全部 Optional<T> で書き直したりしてました. https://github.com/apple/swift/issues/54184
ええ〜。その書き換えは大変だ・・・
Avatar
Kishikawa Katsumi 10/31/2022 10:52 PM
https://forums.swift.org/t/pitch-if-and-switch-expressions/61149 ifとswitchが式になる、これはできるだけ早く採用されてほしい。
Hey all, an early-stage pitch for this feature. No implementation quite yet but hopefully not too far off. if and switch expressions This proposal introduces the ability to use if and switch statements as expressions, for the purpose of: Returning values from functions, properties, and closures; Assigning values to variables; and Declaring v...
Avatar
これかなり前から文指向だからやらないよって言ってたやつですねえ 最近そういうのが多いな ( if let foo { とか ) 割とコアチームの意見というよりクリスラトナーの意見って感じだったのかなあと思う
11:20 PM
文法がややこしくなって曖昧なケースとか生じそうなのとか、breakとの併用とかどうなるのとか思うけど、提案の通り func の return 省略と同じで 1文に限るとか、いろいろ制約いれてけば無難に導入できるんかな。
Avatar
Kishikawa Katsumi 10/31/2022 11:50 PM
へえ、やらない一覧に入ってたやつもこれから変わってくんですかね。
Avatar
そんな気がしますねえ
11:51 PM
この前のマクロのピッチもそういうやつですね まあマクロは、十分材料出尽くしたら検討してもいい、ぐらいの余地はありましたけど
Avatar
Kishikawa Katsumi 10/31/2022 11:53 PM
https://github.com/apple/swift-evolution/blob/main/commonly_proposed.md#control-flow-closures-optional-binding-and-error-handling これか。確かによほどじゃないと採用されないリストにあるね。
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/commonly_proposed.md at main · apple/swift-evolution
Avatar
if/else and switch as expressions: These are conceptually interesting things to support, but many of the problems solved by making these into expressions are already solved in Swift in other ways. Making them expressions introduces significant tradeoffs, and on balance, we haven't found a design that is clearly better than what we have so far.
11:57 PM
ここに書いてあるからには significant tradeoffs について言及されてほしいな・・・導入は別に良いと思うけど
Avatar
Kishikawa Katsumi 10/31/2022 11:57 PM
せやな。どんなトレードオフがあるんだろう。ユーザーじゃなくてコンパイラかな。
Avatar
たしかに型推論は難しくなるけど、もうすでにResult Builderで同等のものが入ってるから、問題ないはずですね。Result Builderのときにone-way constraintが発明されたから、そういう意味ではそこは技術進歩で解決してる。
Avatar
うーん、値型&ミュータブルの世界には文指向がマッチしてると思うんだけどなぁ。
Avatar
Kishikawa Katsumi 11/1/2022 2:45 AM
その辺がトレードオフってやつなのかな。
2:46 AM
私は単純にスッキリ書ける場面が増えて実用的だと思ってますけど、どの辺が困る感じですか?
Avatar
困るわけじゃないんですけどねー。過剰に式で書かれることにならないかなぁと。
2:49 AM
var に入れて if で分岐して変更すればいいものが、無理やり let にしようとして巨大な if 式で書かれたりとか。
2:50 AM
まず var を使うことを受け入れるのが Swift の第一歩だと思うんですよね。
Avatar
var は下までずっとスコープが伸びるのがちょっと抵抗ありますけど、move が来ればそれもなくなるからなぁ
Avatar
Avatar
Iceman
var は下までずっとスコープが伸びるのがちょっと抵抗ありますけど、move が来ればそれもなくなるからなぁ
確かにそうですね。あまり長いスコープを作るの自体が良くないのかもしれませんが。
Avatar
Kishikawa Katsumi 11/1/2022 2:55 AM
まず var を使うことを受け入れるのが Swift の第一歩
あ、なるほど。読み違えてた。値型&「ミュータブル」か。
2:56 AM
なるほどねえ。値型ならイミュータブルに固執しなくても、ということなんですね。でif/switch式はそれに逆行するんじゃないか、と。
2:57 AM
if/switch式が使えてしまうと、無理にletにしようとする力が働いてしまう、、と。
Avatar
値型ならイミュータブルに固執しなくても
var が直接ミュータブルに結びついているわけではなくて、値型はミュータブルでもイミュータブルクラスと同等なので、標準ライブラリでも mutating func がいっぱい使われているし、無理して let にこだわる必要はないよということですね。
2:59 AM
Each branch of the if, or each case of the switch, must be a single expression.
これがあるからそんなに長大な if 式が作られたりはしないかなぁ。
Avatar
Kishikawa Katsumi 11/1/2022 3:01 AM
クロージャが中に書かれそうだな。
3:01 AM
って考えるとif式の中は複数行書けた方がいいんじゃないかな。
3:02 AM
いや、わからん。
Avatar
↓こんなの生まれそうですよね😂 let foo = if isBar { { ... }() } else { Foo(...) } (edited)
Avatar
Kishikawa Katsumi 11/1/2022 3:15 AM
書きそう。さらに三項演算子を使ったり。。。
Avatar
Alternatives Considered and Future Directions Sticking with the Status Quo The list of commonly rejected proposals includes the subject of this proposal:
if/else and switch as expressions: These are conceptually interesting things to support, but many of the problems solved by making these into expressions are already solved in Swift in other ways. Making them expressions introduces significant tradeoffs, and on balance, we haven't found a design that is clearly better than what we have so far.
The motivation section above outlines why the alternatives that exist today fall short. One of the reasons this proposal is narrow in scope is to bring the majority of value while avoiding resolving some of these more difficult trade-offs. The lack of this feature puts Swift's claim to be a modern programming language under some strain. It is one of the few modern languages (Go being the other notable exception) not to support something along these lines.
Avatar
omochimetaru 11/1/2022 8:18 AM
1. 状況を限定することでtradeoffを避けました 2. 他の子はみんなやってる
Avatar
{} の中が single expression に限定されてしまうのが Swift と相性悪そう。イニシャライザで初期化終わらず var にして後から変更加えるやつとか結構いる気が。 URLRequest とか。
tashikani 4
Avatar
5.7からこれで書けるの何でだろ extension String? {}
Avatar
omochimetaru 11/1/2022 5:21 PM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0361-bound-generic-extensions.md at main · apple/swift-evolution
t_naruhodo 1
Avatar
let foo: Int switch condition { case pattern: foo = 0 ... default: return // early return }
6:23 AM
これを
6:23 AM
let foo = switch condition { case pattern: 0 ... default: return // early return }
6:24 AM
こう書けたりするのだろうか
6:24 AM
後者はリッチなガード文として嬉しい反面、分かりづらそう…
Avatar
omochimetaru 11/3/2022 8:24 PM
An exception to this rule is if a branch either returns, throws, or traps, in which case no value for the overall expression need be produced.
例外として、もし分岐がreturnやthrowsをしている場合は式の値を用意しなくて良い とあるんで、returnになってる分岐もアリみたいですね、かけそう。
8:25 PM
guard let foo = switch condition { case pattern: 0 ... default: nil } else { return } こう書いたほうがguardであることが表明できるけど、ちょっと行が増えちゃいますね (edited)
Avatar
returnやthrowの値をNeverにしたら解決するヤツだったりしない? (edited)
Avatar
omochimetaru 11/4/2022 1:27 AM
それやると let a = 1 + return とかも認められる事になるので話が広がってそう
Avatar
挙げたのは値なしの return だったけど、switch 式としての型と関数の返り値の型が同じだとバグを埋め込みそうで怖いですね
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/variadic-generics.md at variadic-generics-vision · hborla/swift-evolution
1:30 PM
ホーリーさんの可変長ジェネリクスのビジョン文書 小さめなマニフェストって感じだ
1:31 PM
この前のピッチだと長さは固定だったけど、こっちだと<First, Rest…>による長さのマイナス1計算の話が増えてるかな
Avatar
Kishikawa Katsumi 11/11/2022 11:39 AM
@main struct Main { static func main() { testPowerAssert() } static func testPowerAssert() { let a = 4 let b = 7 let c = 12 #powerAssert(max(a, b) == c) #powerAssert(a + b > c) struct Person { let name: String let age: Int var isTeenager: Bool { return age <= 12 && age >= 20 } } let john = Person(name: "John", age: 42) let mike = Person(name: "Mike", age: 13) #powerAssert(john.isTeenager) #powerAssert(mike.isTeenager && john.age < mike.age) } } ^ こんなマクロを書くと (edited)
11:40 AM
@main struct Main { static func main() { testPowerAssert() } static func testPowerAssert() { let a = 4 let b = 7 let c = 12 PowerAssert.Assertion("#powerAssert(max(a, b) == c)", line: 12, verbose: true).assert(max(a, b) == c).record(expression: max(a, b), column: 13).record(expression: a, column: 17).record(expression: b, column: 20).record(expression: max(a, b) == c, column: 23).record(expression: c, column: 26).render() PowerAssert.Assertion("#powerAssert(a + b > c)", line: 13, verbose: true).assert(a + b > c).record(expression: a, column: 13).record(expression: b, column: 17).record(expression: a + b > c, column: 19).record(expression: c, column: 21).render() struct Person { let name: String let age: Int var isTeenager: Bool { return age <= 12 && age >= 20 } } let john = Person(name: "John", age: 42) let mike = Person(name: "Mike", age: 13) PowerAssert.Assertion("#powerAssert(john.isTeenager)", line: 27, verbose: true).assert(john.isTeenager).record(expression: john.isTeenager, column: 18).record(expression: john, column: 13).render() PowerAssert.Assertion("#powerAssert(mike.isTeenager && john.age < mike.age)", line: 28, verbose: true).assert(mike.isTeenager && john.age < mike.age).record(expression: mike.isTeenager, column: 18).record(expression: mike, column: 13).record(expression: john.age, column: 37).record(expression: john, column: 32).record(expression: mike.isTeenager && john.age < mike.age, column: 41).record(expression: mike.age, column: 48).record(expression: mike, column: 43).render() } } ^ こういうコードに展開されて、
11:41 AM
#powerAssert(max(a, b) == c) | | | | | 7 4 7 | 12 false #powerAssert(a + b > c) | | | | 4 7 | 12 false #powerAssert(john.isTeenager) | | | false Person(name: "John", age: 42) #powerAssert(mike.isTeenager && john.age < mike.age) | | | | | | | | false | 42 | | 13 | | | Person(name: "Mike", age: 13) | | false | Person(name: "John", age: 42) Person(name: "Mike", age: 13) ^ このような結果が得られる。
Avatar
マクロの使い方としてめっちゃ良いユースケースですね
Avatar
Kishikawa Katsumi 11/11/2022 11:48 AM
ですよね。SwiftのマクロがAST => AST’っていう仕組みになってるからうまくハマる。
11:49 AM
強いていうならASTがもうちょっとリッチだと嬉しい。
11:50 AM
もうちょいいろいろなケースに対応したらフォーラムのスレッドに書いてみようと思う。
Avatar
良いですね キャッチーだと思う
Avatar
Kishikawa Katsumi 11/11/2022 11:53 AM
a + b > c これが [a, +, b, > c] みたいなASTの構造になるとかがちょっと辛い。左辺と右辺、のような概念がほしい。
Avatar
演算子の結合を考慮したツリーじゃなくて配列なのが不便ッテ意味ですか? (edited)
Avatar
Kishikawa Katsumi 11/11/2022 11:54 AM
そうですね。 > のparentを取っても + のparentを取っても a + b > c になってしまうのが使いにくい。
Avatar
Introduce a library that implements the semantics of Swift user-defined operators and precedence groups. The primary operation is a &quot;fold&quot;, which takes a sequence expression (i.e....
Avatar
Kishikawa Katsumi 11/11/2022 11:55 AM
+ のparentが a + b になるか、 +, < の左辺と右辺が取れる、みたいなのが欲しい。
Avatar
これ使えばツリー化してくれるっぽいですよ
Avatar
Kishikawa Katsumi 11/11/2022 11:57 AM
ありがとう。やってみる。
11:57 AM
マニュアルはこれかな。
Avatar
Kishikawa Katsumi 11/11/2022 11:58 AM
ざっと検索したときに見たんだけどuser-definedだから違うかなと思ってしまった。
Avatar
マクロいろんな可能性があっていいですね
Avatar
stdlibの基本オペレータの定義は組み込みで入ってるみたいですね。 import SwiftSyntax import SwiftParser import SwiftOperators var opPrecedence = OperatorTable.standardOperators // Use the Swift standard library operators let parsed = Parser.parse(source: "x + y * z") dump(parsed) // contains SequenceExprSyntax(x, +, y, *, z) let folded = try opPrecedence.foldAll(parsed) dump(folded) // contains InfixOperatorExpr(x, +, InfixOperatorExpr(y, *, z)) (edited)
Avatar
Kishikawa Katsumi 11/11/2022 11:59 AM
OperatorTable.standardOperators これがStdLibのためのやつか
🙆‍♂️ 1
Avatar
Kishikawa Katsumi 11/11/2022 12:08 PM
a + b > c ▿ ExprListSyntax ▿ IdentifierExprSyntax - unexpectedBeforeIdentifier: nil ▿ identifier: identifier("a") - text: "a" ▿ leadingTrivia: [] - pieces: 0 elements ▿ trailingTrivia: spaces(1) ▿ pieces: 1 element ▿ spaces(1) - spaces: 1 ▿ tokenKind: SwiftSyntax.TokenKind.identifier - identifier: "a" - unexpectedBetweenIdentifierAndDeclNameArguments: nil - declNameArguments: nil - unexpectedAfterDeclNameArguments: nil ▿ BinaryOperatorExprSyntax - unexpectedBeforeOperatorToken: nil ▿ operatorToken: spacedBinaryOperator("+") - text: "+" ▿ leadingTrivia: [] - pieces: 0 elements ▿ trailingTrivia: spaces(1) ▿ pieces: 1 element ▿ spaces(1) - spaces: 1 ▿ tokenKind: SwiftSyntax.TokenKind.spacedBinaryOperator - spacedBinaryOperator: "+" - unexpectedAfterOperatorToken: nil ▿ IdentifierExprSyntax - unexpectedBeforeIdentifier: nil ▿ identifier: identifier("b") - text: "b" ▿ leadingTrivia: [] - pieces: 0 elements ▿ trailingTrivia: spaces(1) ▿ pieces: 1 element ▿ spaces(1) - spaces: 1 ▿ tokenKind: SwiftSyntax.TokenKind.identifier - identifier: "b" - unexpectedBetweenIdentifierAndDeclNameArguments: nil - declNameArguments: nil - unexpectedAfterDeclNameArguments: nil ▿ BinaryOperatorExprSyntax - unexpectedBeforeOperatorToken: nil ▿ operatorToken: spacedBinaryOperator(">") - text: ">" ▿ leadingTrivia: [] - pieces: 0 elements ▿ trailingTrivia: spaces(1) ▿ pieces: 1 element ▿ spaces(1) - spaces: 1 ▿ tokenKind: SwiftSyntax.TokenKind.spacedBinaryOperator - spacedBinaryOperator: ">" - unexpectedAfterOperatorToken: nil ▿ IdentifierExprSyntax - unexpectedBeforeIdentifier: nil ▿ identifier: identifier("c") - text: "c" ▿ leadingTrivia: [] - pieces: 0 elements ▿ trailingTrivia: [] - pieces: 0 elements ▿ tokenKind: SwiftSyntax.TokenKind.identifier - identifier: "c" - unexpectedBetweenIdentifierAndDeclNameArguments: nil - declNameArguments: nil - unexpectedAfterDeclNameArguments: nil 変わってないように見えるな。。。何か間違ってるのかしら。
12:09 PM
ドキュメントのコードをそのままやってみよ。
Avatar
Kishikawa Katsumi 11/11/2022 12:49 PM
できそう。 SwiftParserから返ってきたSyntaxじゃないと期待どおり動かないっぽい。ASTの構造が違うのかな。
👀 1
Avatar
Kishikawa Katsumi 11/11/2022 3:06 PM
シンプルに#assertにしたかったけど、それはどうもSwiftSyntaxが予約してるか何かに使用してるっぽい。
Avatar
Kishikawa Katsumi 11/13/2022 6:51 AM
The idea of AST to AST transformation by macro is excellent. It has very great potential. I want to show one practical example. I have created a proof of concept for the Power Assert library using currently publicly available code. If you write a macro like the following: let a = 4 let b = 7 let c = 12 #powerAssert(max(a, b) == c) #powerAsser...
🎉 2
Avatar
マクロって仕組み的にそのファイル外の情報(型定義とかモジュール名とか)もとれるようになってるんですかね?
Avatar
Kishikawa Katsumi 11/14/2022 6:06 AM
MacroEvaluationContextにモジュール名は渡ってきそうな雰囲気がありますね(今のところ動作環境が専用のCLI経由しかないので固定の文字列)。それ以外は少なくとも議論を読んでる限り最初のうちはないんじゃないかな。ただ自力で読むことはたぶんできる。コンパイラが読める範囲のものは全部読めるだろうし。
Avatar
なるほど。基本はSwiftSyntaxを裏で使った結果が渡ってくるものとイメージしました。
Avatar
Kishikawa Katsumi 11/14/2022 6:50 AM
そうですね。 #colorLiteral(red: 0.5, green: 0.5, blue: 0.25, alpha: 1.0) このマクロでいうと、このマクロをParseした結果のSyntaxとContextが渡されるのでマクロを実装する人はargumentListなどをみていって、最終的にマクロを置換する文字列を返す、となります。
Avatar
コンパイラが読める範囲のものは全部読める
インターフェースとしては ExpressionMacro に渡ってくるのは部分CSTなのと MacroEvaluationContext も外側の情報は渡してこないように見える。 CompilerPluginみたいな感じで、sand-box下で実行されて、外側のソースは読めないっていう仕様への着地もありえる気がします。
(edited)
7:18 PM
実際、純粋なコード加工なら部分CSTだけで良いはずで、 周りの型情報とか他の部分のソース情報も読み取るとなると、 マクロの実行結果が局所的な情報だけで決定しなくなるという事なんで
7:19 PM
そのほうが高機能ではあるが、ユーザーにとってはマクロ展開結果の予測しづらい変動や不具合の原因にもなりえるので難しくなりうる
Avatar
Kishikawa Katsumi 11/14/2022 9:43 PM
確かにそういう制限付きになることもありえるね。既存の#始まりの言語仕様を置き換える、って話があるから #function が実装できる外側のfunctionまでの構造が渡される、っていうのが一番厳しい制限かなあ。
Avatar
#function なるほど確かに。多少外側の情報が必要ですね。 (edited)
Avatar
Kishikawa Katsumi 11/14/2022 11:17 PM
まあしかしコンパイラと同じ権限で動く、っていうのはちょっと楽観的すぎる見通しな気がしてきました。
Avatar
そのへんの仕様によってビルドパイプラインにおいてキャッシュに影響を与える範囲とかも変わってくるんですよねえ
Avatar
Kishikawa Katsumi 11/14/2022 11:22 PM
毎回結果が変わるマクロがあったらどうすんねん(#timestampみたいな)、ってのも議論にあったな。どういう話に進んだのか思い出せないけど。
Avatar
うわあ、なるほど。それめんどくさいな・・・ (edited)
Avatar
Kishikawa Katsumi 11/14/2022 11:22 PM
まさに毎回フルビルドになるのか、みたいな懸念が書いてあったと思う。
Avatar
Kishikawa Katsumi 11/16/2022 9:28 PM
https://github.com/apple/swift/blob/2fc16373b32a335f8e0f74f0289bae6f217e4ce9/include/swift/Option/Options.td#L1721-L1726 マクロを使う手段はまだない、って書いたけど実はもうコンパイラに入っててフラグ指定したら使えるのかしら?
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
どうなんだろう そうだとしたら、なにかテストケースがどっかにありそう
Avatar
Kishikawa Katsumi 11/16/2022 9:34 PM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
9:36 PM
// RUN: %target-swift-frontend -enable-experimental-feature Macros -dump-ast %s -module-name MacrosTest 2>&1 | %FileCheck %s
9:36 PM
-enable-experimental-feature Macros これで有効化していそうだけど、定義したプラグインを読み込ませている箇所が見当たらないなあ
9:37 PM
struct StringifyMacro: _CompilerPlugin { static func _name() -> (UnsafePointer<UInt8>, count: Int) { var name = "customStringify" 名前が stringify じゃない・・・
9:38 PM
// RUN: %empty-directory(%t) // RUN: %target-build-swift -Xfrontend -disable-availability-checking -I%platform-module-dir/../.. -L%platform-dylib-dir/../.. -emit-library -emit-library-path=%t/%target-library-name(MacroDefinition) -working-directory=%t -module-name=MacroDefinition %S/Inputs/macro_definition.swift // RUN: %target-swift-frontend -L%platform-dylib-dir/../.. -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -disable-availability-checking -dump-ast -primary-file %s | %FileCheck %s お、こっちはそれっぽいですね
9:38 PM
Inputs/macro_definition.swiftMacroDefinition モジュールとしてビルドして
9:39 PM
次のコマンドでさっきみつけた -load-plugin-library で、 MacroDefinition を読み込ませている
9:39 PM
同じようにやったら動きそう
9:39 PM
あーわかった https://github.com/apple/swift/blob/92d970497ec165aef541ed032fcdac4abd578e55/test/Macros/macros.swift こっちのテストケースは -dump-ast なんで
9:40 PM
#stringify をパースさせているだけだ。 stringify は実際には提供されていない。パースから先は動かないんだと思う。
Avatar
Kishikawa Katsumi 11/16/2022 9:40 PM
なるほど。ありがとう。やってみる。
Avatar
いや、macro_plugin.swift-dump-ast してるだけだな・・・
9:41 PM
macro_plugin_exec.swift は、 -o で実行ファイル作って、実行していますね
9:41 PM
いけそう。
Avatar
Kishikawa Katsumi 11/16/2022 9:42 PM
今はダイレクトにAST変換をするんじゃなくていったんファイルにソースコードの形にするわけね。
Avatar
  // RUN: %target-build-swift -Xfrontend -disable-availability-checking -I%platform-module-dir/../.. -L%platform-dylib-dir/../.. -emit-library -emit-library-path=%t/%target-library-name(MacroDefinition) -working-directory=%t -module-name=MacroDefinition %S/Inputs/macro_definition.swift // RUN: %target-build-swift -L%platform-module-dir/../.. -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) %s -o %t/main // RUN: %target-run %t/main (edited)
Avatar
Kishikawa Katsumi 11/16/2022 9:43 PM
いや、ファイルになるのは実行形式だけか
Avatar
ダイレクトにビルドまでいけてそうです
Avatar
Kishikawa Katsumi 11/16/2022 9:43 PM
そうだね
9:45 PM
そうすると実は一般に機能を解放するかどうかが論点か。
Avatar
あとはまあSwiftPMが対応してくれないとこのままだとコマンドラインでコンパイルする使い方しかできないから一般利用は厳しいですね
9:47 PM
うーん、 #stringify のテストがなんで通るんだろう・・・ -dump-ast はたしか型チェックするから、どっかで定義されてないとダメそうなんだけど
Avatar
Kishikawa Katsumi 11/16/2022 9:48 PM
マクロの提供はパッケージ単位になるだろうしねえ。
Avatar
MODES: -dump-ast Parse and type-check input file(s) and dump AST(s) -dump-parse Parse input file(s) and dump AST(s)
Avatar
Kishikawa Katsumi 11/16/2022 9:50 PM
SwiftSyntaxの方に実体があるんじゃないの?
9:50 PM
これが固定で読み込まれてるんかな?
Avatar
Kishikawa Katsumi 11/16/2022 9:52 PM
動かしてみないとわからんな。
Avatar
Kishikawa Katsumi 11/17/2022 8:09 AM
https://forums.swift.org/t/pitch-expression-macros/61499 改めてPitchとProposalが投稿された。 まだコンパイラ本体で試すのは難しいっぽい。 (edited)
Hey all, Following up on the vision for macros from last month, here is a pitch for expression macros. Expression macros are used as expressions in the source code (marked with #) and are expanded into other expressions. Expression macros can have parameters and a result type, much like a function, which describes the effect of the macro expan...
Avatar
Kishikawa Katsumi 11/17/2022 8:16 AM
createUniqueLocalName()gensym だな。(マクロが新しい変数や関数を定義する場合、既存のコードと衝突しない名前を自動的に作ってくれる。)
8:18 AM
TrackingやLoggingをFunction単位で差し込めるようなAspect Oriented Programmingを実現できるような機能はいったん見送りかな? (edited)
8:21 AM
マクロは引数と戻り値が型チェックされて、型があってても失敗するような引数が来た場合はエラー情報を返せるインターフェースがある、 具体的になったのはそれくらいかな?
Avatar
考えてみればマクロは関数みたいな感じだから,型とか関数を丸ごと作るとかはできなさそうだ
6:15 AM
コード生成の需要はまだまだ続きそうやな (edited)
Avatar
Kishikawa Katsumi 11/22/2022 6:40 AM
そうですねえ。いくつかのコード生成はマクロに置き換えられると思いますけど今のところ全部マクロで、みたいなのはまだまだ先っぽい。
Avatar
#init みたいなのなかったですっけ
Avatar
たしかにsyntaxのテストケースでは見た
8:57 AM
けど提案書の仕様にはハマらないようにみえる
Avatar
#init 需要ありそうだけどな〜残念ですね
Avatar
あーわかった
9:03 AM
vision documentのほうにはこういうのも書いてある
9:03 AM
// In the standard library macro(contexts: [.memberDeclaration], external: "MyMacros.MemberwiseInit") func memberwiseInit(access: Access = .public)
9:03 AM
今回のピッチはあくまで expression macro だから
9:03 AM
// In library macro(contexts: [.expression], external: "MyMacros.ColorLiteral") func colorLiteral(red: Double, green: Double, blue: Double, alpha: Double) -> _ColorLiteralType
9:04 AM
expressionの出てくるところでexpressionとして展開される限定のマクロなんだ
9:04 AM
少しずつ仕様をまとめていくつもりなんだな
9:05 AM
2023年にやりたい事リストにはマクロも書いてあるから、来年ちょっとずつ進んでいくんだろう。
9:05 AM
There’s a lot of exciting work going on in the Swift project, and it’s hard to keep track of it all because it’s happening in many different repositories, pull requests, and forum threads. To give the community a better view of the big picture, the Core Team surveyed workgroups and developers across the project and collected information about wh...
Avatar
Kishikawa Katsumi 11/22/2022 9:05 AM
Proposalには出てこなかったからちょっとずつやってくんでしょうね。
9:06 AM
ただマクロはVisionの時点で導入自体に対する反対意見も結構あったから入ることは既定路線みたいな感じになってるのは驚いた。
Avatar
そうですね。いつのまにやら方向性が変わってきた。
9:08 AM
何が背景にあるんでしょうね。 Swift compiler内部では、結構pythonとかCプリプロセッサを使ったコード生成が多用されているので、Swiftコンパイラのセルフホストが内部的に大テーマとして決まってて、 C++ interoperabilityと合わせて考えると、コンパイラ実装するならマクロ必要だよね、という感じかなあ?
9:10 AM
SwiftUIみたいなユーザー向けフレームワークでAppleが出すもので、ってパターンには内容的に違いそうだし
Avatar
Kishikawa Katsumi 11/22/2022 9:13 AM
マクロを書くにはSwiftSyntaxをもうちょいラップした何かが欲しいな。SwiftSyntaxで返ってくるのはちょっと冗長すぎるのでもうちょい高レベルな構造で返ってくるのが欲しい。。。といってもほとんどの簡単なマクロを書くにはいらないと思うけど。
Avatar
You can gather type definitions from Swift source code. - GitHub - omochi/SwiftTypeReader: You can gather type definitions from Swift source code.
9:14 AM
まさにそのためにこれを作ってる (edited)
Avatar
Kishikawa Katsumi 11/22/2022 9:15 AM
なるほど確かに!
9:15 AM
これは来年大ヒットしそうだな。
Avatar
マクロ文明が花開いてそこらじゅう黒魔術だらけになったらウケるな。 (edited)
Avatar
Kishikawa Katsumi 11/22/2022 10:23 AM
単なる関数でいいものをマクロにする、とかはありそう。
Avatar
そういうのもちょっと起きそうですよね。 やりたいことを言語機能でやるよりコード展開で考えるほうがすぐにやり方が思いついたので・・・みたいな。
Avatar
Kishikawa Katsumi 11/22/2022 10:46 AM
なんかいいアイデアあるかなっていろいろ考えたときにだいたい関数にまとめるだけのほうがいいよねって自分ではなった。
Avatar
Kishikawa Katsumi 12/2/2022 11:38 AM
It is intended that MacroEvaluationContext will grow over time to include more information about the build environment in which the macro is being expanded. For example, information about the target platform (such as OS, architecture, and deployment version) and any compile-time definitions passed via -D, should be included as part of the context.
ちょっと改訂された。MacroEvaluationContextにはビルド設定とかプラットフォームの情報とか入ってくる予定らしい。 https://github.com/DougGregor/swift-evolution/commit/d101cff73398386b471798b750d6f89798721211
(edited)
Avatar
おお。
Avatar
Kishikawa Katsumi 12/2/2022 11:42 AM
compile-time definitions passed via -Dが取れるのはなんか応用範囲が広そうな気がする。
Avatar
りゅーせい 12/5/2022 7:43 AM
初めまして、質問よろしいでしょうか? 特定の「View」以外の場所をタップした時に処理を実行したいのですが、その様な事はできるのでしょうか? 調べても出てこなかったので、もしできる様でしたら誰かわかる方ご教授頂きたいです。
Avatar
omochimetaru 12/5/2022 7:47 AM
UIKit前提で言うと、「XX以外の場所をタップした」というイベントを取る方法は無いと思います。特殊な方法はあるかもしれないけど。 自分だったらそういう場合は、「XX以外の場所」に該当する部分に、見えないボタンとかTap Gesture Recognizerを仕込んでおいて、タッチイベントを検出するように作ります。 (edited)
7:49 AM
画面全体の領域を持ってる親ビュー側のhit testを改造して、子にタッチが到達する前に何をタッチしてるか判定する、みたいなパターンもやる事があります。
Avatar
やりたいUIパターンはUIPopoverController辺りが近そうな気がするので、公式のドキュメントやexampleを見ても良いかと思います
Avatar
りゅーせい 12/5/2022 8:22 AM
なるほど、お二人ともありがとうございます。 実は「containerView」をタップした際に反応して欲しかったんですけど、それをやると「presentedView」をタップした時にも反応してしまうので、「presentedView」以外をタップした時に
8:22 AM
反応するってのがあればそれでどうにかしようとしてたんですけど、そんなものは無さそうですね。
8:25 AM
素直に背景としてもう一つViewをつけてそれをタップした時に反応する様に書いてみます。 そんなイベント判定はないってのも勉強になりました。 ありがとうございます🙇‍♂️
Avatar
Kishikawa Katsumi 12/5/2022 12:28 PM
Swiftのマクロ、ファイルが読めるならバイナリをソースコードに埋め込む、っていうのできそうだけどファイル読めるかなあ。
Avatar
全然関係ないですけど次のCにもそういうマクロが入るっぽい https://yohhoy.hatenadiary.jp/entry/20220915/p1
Avatar
ファイルをコードに埋めちゃうのってプロセスの実行モデル的に効率悪い事があったりしないのだろうか ワンファイル実行ファイルにできてデプロイしやすいとか、そういうメリットはあるけど
Avatar
もしSwiftでインラインアセンブリが書ければ、アセンブリの機能にincbinというのがあって、アセンブラがファイル読んで埋め込んでくれる
Avatar
Kishikawa Katsumi 12/5/2022 12:32 PM
お、 #embed 偶然作るならそういう名前かなと考えてたのと一緒だ😅
12:32 PM
主にコマンドラインツール作るとき用かな。
12:33 PM
バンドルを持てない、持てなくはないけど手間が異様に増えるやつ。
Avatar
バンドルあると配布がすごい面倒くさいですよね
Avatar
Kishikawa Katsumi 12/5/2022 12:34 PM
然り。作者も利用者もどっちも大変。
Avatar
なるほど
Avatar
Kishikawa Katsumi 12/5/2022 12:34 PM
MintやSwiftPMでいいやんみたいな話もあるけど。
12:35 PM
(私はMintやSwiftPMでやるのそんな便利と思ってない。)
Avatar
バイナリ配布じゃないと壊れそうですね→swiftpm
Avatar
Kishikawa Katsumi 12/5/2022 12:36 PM
Cの例にあるけど今だったらシェーダとかMLのモデルを埋め込む、みたいな需要もあるのかしら。CLIツールに。
Avatar
しかしファイルを読めてしまうということは、ビルドシステムに読み込むファイルが依存物であることを伝えないといけないので大変だ
12:38 PM
プラグインでそういうのはできるんですかね
Avatar
Kishikawa Katsumi 12/5/2022 12:38 PM
ファイルが読めたらこういうことができて嬉しい、ってことで聞いて(お願い)みよう。
Avatar
例によってsandbox execされてて見えなそう
Avatar
Kishikawa Katsumi 12/5/2022 12:38 PM
プラグインはLintのプラグインとかあるからできるんじゃないかな。
12:38 PM
できない?
Avatar
ああ、コマンドプラグインは見えますね
12:39 PM
書き込みするときは、権限取得するやつがでる
12:39 PM
ユーザーがyesって打つやつ
12:39 PM
読み込みはフリー
Avatar
Kishikawa Katsumi 12/5/2022 12:40 PM
まあ確かに読み込みのみにするとか、パーミッションが必要とか妥協点はありそう。
Avatar
Kishikawa Katsumi 12/6/2022 6:18 AM
Dartにもマクロの提案があるらしい。はやりなんかな。Dartのマクロはパッと見てJavaのアノテーションぽい気もする。 https://github.com/dart-lang/language/tree/master/working/macros
Design of the Dart language. Contribute to dart-lang/language development by creating an account on GitHub.
Avatar
Dartも欲しそうですねマクロ
6:24 AM
@freezedっていうコード生成ツールがデファクトになってそうだけど、やっぱり公式で欲しいと思う
6:27 AM
kaptみたいにリフレクションっぽいAPIでメタタイプからフィールドやメソッドを引っ張り出せるようになってる?
Avatar
Kishikawa Katsumi 12/6/2022 6:27 AM
なんか見た目も動きの説明もJavaのアノテーションっぽいですよね。
Avatar
ぽいですよね。マクロというよりアノテーションプロセッサー的な印象
Avatar
omochimetaru 12/7/2022 5:54 PM
Hi all, Based on discussion in the first pitch of expression macros, I've revised the proposal. The updated proposal is here. Changes include: Rename MacroEvaluationContext to MacroExpansionContext. Remove MacroResult and instead allow macros to emit diagnostics via the macro expansion context. Remove sourceLocationConverter from the macro e...
5:56 PM
expression macroのプロポーザルが更新された 提案書の中で岸川さんのpower assertがサンプルとして掲載されてる (edited)
5:57 PM
swiftpmでマクロパッケージを定義する書き方なども言及が入った
Avatar
Kishikawa Katsumi 12/7/2022 6:09 PM
func type(of node: ExprSyntax) -> Type? マクロの型情報の話あるけどこのへんは将来の拡張予定って扱いっぽいな。
6:09 PM
アスペクト指向的なすべての関数に適用、みたいなのも後回しって書いてあるのかな。
Avatar
omochimetaru 12/7/2022 6:18 PM
本当だ,future directionの章に型情報の取得についての議論が書いてありますね
6:19 PM
まさに書いてある通りで、型情報をユーザーに渡そうとすると、コンパイラ内部のデータ構造を安定化させてAPIを整理しないといけないから大仕事なのはそうだと思います 自力で同じ事をやってるのでわかる・・・
Avatar
Kishikawa Katsumi 12/7/2022 6:20 PM
func type(of node: ExprSyntax) -> Type? しかしこれは完璧に求めていたものって感じですごい。 (edited)
Avatar
omochimetaru 12/7/2022 6:20 PM
そうですね。
Avatar
Kishikawa Katsumi 12/7/2022 6:23 PM
さすがに導入はもう決定でいいのかな。Pitch1にも反対意見はなかったように見えるし。
Avatar
omochimetaru 12/7/2022 6:24 PM
大筋は既定路線でしょうねー
6:25 PM
形式的にはSEやるはずだけど、例の如く、ご意見募集であって投票ではないので。 (edited)
Avatar
omochimetaru 12/7/2022 6:52 PM
Hi all, Based on discussion in the first pitch of expression macros, I've revised the proposal. The updated proposal is here. Changes include: Rename MacroEvaluationContext to MacroExpansionContext. Remove MacroResult and instead allow macros to emit diagnostics via the macro expansion context. Remove sourceLocationConverter from the macro e...
6:52 PM
if式のレビュー始まった!
Avatar
omochimetaru 12/7/2022 7:00 PM
返り値と代入時に限定してる。
Avatar
Kishikawa Katsumi 12/8/2022 1:47 AM
Hello, Swift community! The review of SE-0380: if and switch expressions begins now and runs through December 21st, 2022. 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 by email or DM. Whe...
🙏 1
Avatar
なんかぶっ壊れそうで漠然と怖いんだけど大丈夫なんかな笑
Avatar
existentialとgenericsの一級化が済んでるから、結構良い感じになると思ってる。昔やったらAny祭りだったがw
Avatar
あーそれが効いてくるのか。いいね。
Avatar
let view = if foo { Image(...) } else { Text(...) } これでviewがany Viewになってくれると最高
Avatar
omochimetaru 12/8/2022 3:40 AM
その場合はview: any Viewがいりそう
3:40 AM
推論が完全な双方向にはしないって書いてある
Avatar
流石に無理か🤕
3:40 AM
解釈可能な最大の型を指定してくれたら嬉しかったが、計算時間が足りないか
Avatar
omochimetaru 12/8/2022 3:41 AM
// invalid: let x = if p { nil } else { 2.0 } // valid with required type context: let x: Double? = if p { nil } else { 2.0 } (edited)
Avatar
なるほどね
Avatar
omochimetaru 12/8/2022 3:41 AM
推論からexistentialを解く挙動って多分今もどこにもないんよね
Avatar
実際無理なんじゃないかと思ってる
3:42 AM
計算量的に
Avatar
omochimetaru 12/8/2022 3:42 AM
まあ候補めちゃめちゃあるしね
3:43 AM
any CustomStringConvertible とか通りすぎて逆に不便になりそう
Avatar
最大値取れないと価値は無いっすね
3:44 AM
あと、それするにしても、existential/genericsに、普遍的な縛りを明示できるようになってからだろう、というのもある
3:44 AM
any Sequence<.Element=Int> みたいなやつ
Avatar
any Sequence<Int> はもうできるんじゃないですか? primary associatedtype に限らずって話?
Avatar
あ、もう出来るのか。
5:09 AM
ただ、最大を指定できるようにするとどうしても、それより大きな範囲で出来る必要がありそうです
Avatar
@swift-5.7.3 let numbers: any Sequence<Int> = [2, 3, 5] print(numbers.reduce(0, +))
Avatar
Avatar
koher
@swift-5.7.3 let numbers: any Sequence<Int> = [2, 3, 5] print(numbers.reduce(0, +))
10
Avatar
自動で共通のスーパータイプを見つけてくると、意図せず Any になっちゃったりして難しいかもですね。あと、 any View の場合は self conformance 問題って解決されたんでしたっけ?まあ、 View は結局 ViewBuilder で組み立てるから if 式使う必要なさそうですが。
Avatar
omochimetaru 12/8/2022 5:14 AM
解決が何を指すかですが existential は self conform しないし、させる方法も今は無いです
5:15 AM
protocol P: Equatable {} struct S: Equatable { var a: any P } ↑これが通せないのでめっちゃ不便だということを最近気づきました
Avatar
「解決」は、前に話してた any ViewAnyView を代替できるようになるには、 self conformance がないとダメだって問題が解決したか。
Avatar
Avatar
koher
「解決」は、前に話してた any ViewAnyView を代替できるようになるには、 self conformance がないとダメだって問題が解決したか。
omochimetaru 12/8/2022 5:33 AM
してない!
Avatar
self conformanceないと結構不便な場面あるよね・・・
Avatar
Kishikawa Katsumi 12/8/2022 1:47 PM
マクロでコマンドプラグインと同等のパーミッションみたいな仕組みでファイルにアクセスしたい、っていうのを聞いてみたよ。 https://forums.swift.org/t/pitch-2-expression-macros/61861/9 (edited)
I am considering using macros to embed binaries into Swift source code. EXAMPLE: let data = #embed("images/icon.png") // ^ This macro will generate the code below. let data = Data([0x4d, 0x49, 0x54, ..., 0x65, 0x6e, 0x73]) Similar to the #embed macro in C23. This would be useful for applications that do not have bundles, such as command-lin...
👀 1
Avatar
Kishikawa Katsumi 12/8/2022 9:00 PM
Yes, I consider this a natural extension to the proposal, and probably one of the first ones we should do. I think it'll need both SwiftPM manifest file changes and new API in MacroExpansionContext.
マクロからファイルアクセスの計画はあるみたい。
Avatar
Kishikawa Katsumi 12/8/2022 9:16 PM
The MacroExpansionContext isn't going to directly touch the file system---it's going to ask the compiler/SourceKit (whomever it is talking to) to give it the contents of the file as a buffer.
ファイルシステムにマクロ処理系がアクセスするのではなくて、構文木と同様にシステム(コンパイラ?)からバッファとして渡されるほうがよさそう、ということらしい。確かにそのほうがスマートかも。
Avatar
omochimetaru 12/9/2022 2:58 AM
そうすればマクロ評価時に読み込んだファイルが把握できて、ビルドキャッシュが制御できるのか。
Avatar
Kishikawa Katsumi 12/9/2022 3:16 AM
ビルドの最初に決定したいってことならPathで取り回しても一緒な気がするけど、読んでくれるというのはこちらとしててはありがたい。
Avatar
omochimetaru 12/9/2022 3:20 AM
ask to give contentsというのは事前に読むという意味ではなくて、 context.files[“image.png”].data みたいな感じでラップしたファイルIOのAPIを通す、という意味だと思いました
Avatar
岸川さんがレアカードみたいになってる
Avatar
omochimetaru 12/9/2022 3:22 AM
先に全部読んでおくだとメモリ使いすぎちゃうので。 ラップしたAPIを通すことでマクロ評価時に読み込んだファイルが特定できるので、そのファイルが変更されてなければマクロの展開結果をキャッシュできるよね、という話に見えます
Avatar
Kishikawa Katsumi 12/9/2022 3:23 AM
確かに全部読んでから渡すってのはそうですね。理解できました。
Avatar
omochimetaru 12/9/2022 3:24 AM
逆にsandboxの仕組みで触ったファイルを記録できる仕組みがあれば、マクロ実装者は普通にファイルAPI使ってても同じことができそうだけど無いのかな (edited)
Avatar
なるほど。ユーザに自由に読み込ませる口を把握しておくのは賢いですね
Avatar
Avatar
omochimetaru
逆にsandboxの仕組みで触ったファイルを記録できる仕組みがあれば、マクロ実装者は普通にファイルAPI使ってても同じことができそうだけど無いのかな (edited)
omochimetaru 12/9/2022 3:36 AM
あーもしこれがあっても、マクロ処理系のアクセスと、マクロ本体のアクセスの仕分けが必要だから、専用APIの方がいろいろ簡単か
Avatar
Avatar
omochimetaru
if式のレビュー始まった!
if 式と三項演算子、両方ある言語は珍しい? 🧐
Avatar
Avatar
nanasi
if 式と三項演算子、両方ある言語は珍しい? 🧐
たしかに。思いつかない。
Avatar
Ruby とかですかね.
Avatar
りゅーせい 12/10/2022 5:11 AM
画面遷移についてハマったので誰かわかる方いましたらお伺いしたいのですが 「UIPresentationController」クラスの 「dismissalTransitionWillBegin」メソッド内で 「 animate ( alongsideTransition : { [unowned self] _ in ..... } 」メソッド? を扱う際に、思う様に動作しないのでその事について質問したいのですが、誰か「この分野なら答えられそうだな...」という方いらっしゃいますか?もし力になって頂けるのなら質問したいです、、、。
Avatar
Kishikawa Katsumi 12/10/2022 8:58 AM
答えられるかどうかは質問を見ないとわからないのでとりあえず質問を書いたほうがいいですよ。
Avatar
Avatar
Kishikawa Katsumi
答えられるかどうかは質問を見ないとわからないのでとりあえず質問を書いたほうがいいですよ。
りゅーせい 12/10/2022 9:02 AM
わかりました、ありがとうございます。
Avatar
りゅーせい 12/10/2022 9:24 AM
質問です。 簡単にいうとサイドメニューを作りたいのですが、サイドメニューに遷移した際に親Viewが少し下がっているように見せたいんです。 それで遷移する際のアニメーションはうまくいったのですが、画面を閉じる際に思う様に戻っていかなくて、どの様な状態か説明が難しいので、動画を見ていただきたいです。
9:24 AM
Avatar
戻りのアニメーションが「左上原点+スケール縮小」から「初期変形」への遷移になってますね。
9:28 AM
戻りアニメーションの初期状態を、進みアニメーションの最終状態に設定するか
9:28 AM
beginFromCurrentState とかを設定したらいけそうな気がしますね。
9:29 AM
先述されてるtransition系のAPIは使ったことないので詳しくはわからないですけど。
Avatar
りゅーせい 12/10/2022 9:29 AM
あ、そうなんですありがとうございます。 今こんな感じです、
9:30 AM
初期状態に設定するとしたらどこがいいとか、ありますかね?😓
Avatar
うーん、ちゃんと traceView.frame = viewBack の状態が残ってそうですね。
Avatar
りゅーせい 12/10/2022 9:34 AM
一応 dismissalTransitionWillBegin(){ // 閉じる際に実行されるメソッド 初期化フレームの適応 アニメーションメソッド{ 戻る際のframeの適用 }) } っていうふうにも書いてみたんですが、やはり変わらなくて、、、 書く場所が違うとかで解決できるならありがたいんですが。。。
Avatar
戻りアニメーションの開始フレームで、なぜ左上寄せのレイアウトになってるのかを解明すると良さそうです。 (edited)
Avatar
りゅーせい 12/10/2022 9:37 AM
ちなみに dismissalTransitionWillBegin(){ // 閉じる際に実行されるメソッド traceView自体の削除(traceView.removeFormSuperview()) 全く別のtraceView2を変更後のframeの値で生成 アニメーションメソッド{ 戻る際のframeをtraceView2に適用 }) } も試しましたがおんなじ動きでした😭
Avatar
dismissalTransitionWillBegin にブレークポイント貼って時間止めて、 XcodeのView debuggerから何がどういう設定値になっているのか確認するのが良いと思います
Avatar
りゅーせい 12/10/2022 9:38 AM
それですよね
9:38 AM
なるほど
9:39 AM
View debuggerという機能を使った事ないんですが、ちょっと調べてやってみます。
Avatar
予期しないlayout constraintsが何かしら生じてるとか、 translatesAutoresizingMaskIntoConstraints が迷惑な事してないか、とかが気になります。
Avatar
りゅーせい 12/10/2022 9:42 AM
色々frameのpointの部分を変な値にいじってみたのですが、やはりどんなことをしてもx:0 y:0から始まるので、ちょっと調べてみます。ありがとうございます。また調べてる途中で分からないことがあれば頼らせていただくかもです。🙇‍♂️
Avatar
手元で試してみたんですが frame は触らず、 AutoLayout と UIView.transform で操作すると大丈夫そうです。
Avatar
Avatar
omochimetaru
予期しないlayout constraintsが何かしら生じてるとか、 translatesAutoresizingMaskIntoConstraints が迷惑な事してないか、とかが気になります。
りゅーせい 12/10/2022 11:07 AM
ちょっとデバッガーとブレークポイントの使い方調べてみたんですが、何が悪さをしてるのかはわかりませんでした、、、。 ただ一つ分かったのはdismissalTransitionWillBeginメソッドに入ったタイミングではframeのpointはズレてなかったのですが、animateの中に入ったタイミングで、pointが0,0になってました。結局理由は分からず、、、😭
Avatar
Avatar
nanasi
手元で試してみたんですが frame は触らず、 AutoLayout と UIView.transform で操作すると大丈夫そうです。
りゅーせい 12/10/2022 11:07 AM
え!?本当ですか!?!?
11:09 AM
transformなんですが、戻る時はどの様にしましたか?戻りかたが分からなくて、使うの断念したんです。
Avatar
戻る際は .identity にすれば良いです
Avatar
りゅーせい 12/10/2022 11:11 AM
わかりました、やってみます。 わざわざ手元でまで動かして頂いて、 本当にありがとうございます。
Avatar
Avatar
nanasi
戻る際は .identity にすれば良いです
りゅーせい 12/10/2022 11:26 AM
度々すみません、よろしければAutoLayoutのところスクショなど貼ってもらえないでしょうか?自分何か間違えてるかもしれなくて、、、 もうファイル削除してしまってたら大丈夫です、流石に手間ですので
Avatar
りゅーせい 12/10/2022 11:48 AM
あ!できた!できました!!! 今日朝からずっとこの問題と対峙してたんですよね、本当にありがとうございます。すっごい嬉しいです。 もっと早く質問すればよかったです! 回答してくださった皆様!ありがとうございました!!🙇‍♂️
👍 2
Avatar
Hello everyone! The following is a pitch for adding an ability to declared a runtime discoverable attributes in the Swift language. We welcome any feedback or questions about this pitch! Authors: Pavel Yaskevich, Holly Borla, Alejandro Alonso Status: Awaiting implementation Implementation: [Sema/SILGen/IRGen] Implement runtime discoverable...
12:39 PM
カスタムアトリビュートをユーザライブラリ定義して実行時に集めてなんやかんやできるやつの提案
Avatar
データベースのORマッパーとか作る時に、property wrapper使ってプロパティにメタデータ付けるみたいなやつを、実際にラップする副作用無しで実現できそう
Avatar
Kishikawa Katsumi 12/14/2022 2:39 PM
いろいろメタプログラミングの手段を強化しようとしてるのかな。
Avatar
そんな感じがしますね。SwiftUI 3 で派手な事が起きたりするのかなあ。
Avatar
Example macros for the Swift macros effort. Contribute to DougGregor/swift-macro-examples development by creating an account on GitHub.
2:54 PM
マクロを実装して動作させてみるためのスケルトンプロジェクト・・・かな?
2:54 PM
READMEに Adding your own macro の章がある。
Avatar
Kishikawa Katsumi 12/14/2022 2:54 PM
たぶんそうだな。
2:55 PM
これを待ってた。
Avatar
岸川さんはこれのない状態で自力で動かしちゃったからもういらないですね。
2:57 PM
Hi all, @dgoldsmith and I have drafted a pitch outlining new APIs to express predicates natively in Swift code. We hope that this will provide a more robust and ergonomic experience for defining and using predicates in Swift. We plan to introduce this as part of the FoundationEssentials package and we'd love to hear your feedback. Introductio...
2:57 PM
あと、Foundationに NSPredicate みたいなやつを追加する話題(計画の報告?)があって、 これがプロポーザルを見るとマクロを使っている (edited)
Avatar
Kishikawa Katsumi 12/14/2022 2:57 PM
待ってたけど、これはまだコンパイラに統合された形ではうごかないんだな。
Avatar
Avatar
Kishikawa Katsumi
待ってたけど、これはまだコンパイラに統合された形ではうごかないんだな。
mainで実行できるだけって感じがしますね。
2:58 PM
Avatar
Kishikawa Katsumi 12/14/2022 2:58 PM
SwiftSyntax上でマクロの展開までじゃないかな。実行できるかな。
Avatar
クロージャでいいじゃねえかと思ったけど、Predicateオブジェクトは式ツリーオブジェクトなので、ネットワーク越しに送信できたりできるのが良いらしい
Avatar
Kishikawa Katsumi 12/14/2022 2:59 PM
テストケースで動かす、という想定にみえる。
2:59 PM
PredicateやSQLみたいなのはマクロの使い方にマッチすると思う。
3:00 PM
SQLマクロを作る人もいるんじゃないかな。
Avatar
Avatar
Kishikawa Katsumi
SwiftSyntax上でマクロの展開までじゃないかな。実行できるかな。
3:02 PM
同梱されてるxcodeprojにコンパイラフラグが設定されていて
3:03 PM
MacroExamples/main.swift の中にかかれたマクロが展開されたものが実行されるように見えます
Avatar
Kishikawa Katsumi 12/14/2022 3:03 PM
なるほど!めっちゃいいやん。
Avatar
このxcodeprojでそのまま作業すればやりやすそうですね。
Avatar
Kishikawa Katsumi 12/14/2022 3:05 PM
Forkした。今はForkするときにリポジトリの名前つけられるんだな。
Avatar
もうMacroってXcodeに同梱されてるSwiftに実装されてるんですね
Avatar
いや、されてない
3:18 PM
3:18 PM
ツールチェイン落としてきて入れてねって書いてある
Avatar
あ、なるほど。
3:19 PM
流石に早すぎるとは思いました
Avatar
これ難しいですね。アノテーションついてる型や関数を実行時に集めることができるのか。 モジュールを跨いで本来は不可視の型同士をまとめられるの面白そうですね。 DIにすごく便利そう
Avatar
Avatar
Iceman
これ難しいですね。アノテーションついてる型や関数を実行時に集めることができるのか。 モジュールを跨いで本来は不可視の型同士をまとめられるの面白そうですね。 DIにすごく便利そう
難しい。 Attribute.getAllInstances(of: Column.self) って感じで集めるんだと思う。
3:24 PM
例えばpropertyにアノテートしてあった場合は、 Column.init<T, V>(attachedTo: KeyPath<T, V>, custom: Int) がよばれる(いつ?あつめたとき?)ので、KeyPathと合わせてなんとかしておく (edited)
Avatar
VaporでCommandを最初にApplicationに登録する作業とか、ルーティング定義を登録する作業とか、そういうのをある程度自動化できそう
Avatar
Avatar
Iceman
VaporでCommandを最初にApplicationに登録する作業とか、ルーティング定義を登録する作業とか、そういうのをある程度自動化できそう
ああ〜 Vaporでいろいろ登録するやつは確かに相性良さそう。
3:26 PM
なんかこれをフルで活用するなら メタデータ読んでリフレクションするやつと組み合わせないと道具が足りなくなるような気がしなくもない
3:27 PM
I agree partial type is maybe not the best name for this thing. I think type constructor would be a good name if that's the only thing this did (which is pretty much the only thing it does right now). I imagine in the future if we wanted to inspect "generic requirements of a generic type", then this would probably happen on partial types and wou...
3:27 PM
こっちのリフレクションライブラリの話とも繋がってるのかも。
3:28 PM
眺めてみるとマジでSwift6はメタプログラミングの時代になるかもしれん
Avatar
Kishikawa Katsumi 12/14/2022 3:29 PM
反対意見もまああるな。ただこれも導入は決まってるんだろうか。
3:29 PM
私はなかなかおもしろそうと思う。
Avatar
Fluentの@Childrenとかに関しても、今のめっちゃ難しいやり方より子のメタタイプを与えておくだけで最初に集めておいたModel情報からいろんなクエリ投げれてシンプルになるかも
3:29 PM
僕はかなり面白いと思いますね
Avatar
Kishikawa Katsumi 12/14/2022 3:30 PM
メタプログラミングにひかれるのまあまあ中二病っぽいと思うけどしょうがない。
Avatar
コンパイル時か、実行直後にエラーが検知できるならいいと思うんですよね
3:32 PM
そうじゃない使い方されてると変な壊れ方を見つけづらくなって闇になりますが・・・
Avatar
Kishikawa Katsumi 12/14/2022 3:33 PM
この辺の強化はたしかにVaporとかORMに使われるのを想定している感じはあるな。 (edited)
Avatar
Avatar
Iceman
Fluentの@Childrenとかに関しても、今のめっちゃ難しいやり方より子のメタタイプを与えておくだけで最初に集めておいたModel情報からいろんなクエリ投げれてシンプルになるかも
そうなんだよね、すでにユースケースが生じてるから、それをよりスマートに実装するために導入するのは良いよね
Avatar
めちゃくちゃよくある struct FooController { @Get("/api/home") func getHome() async throws -> Response { ... } } みたいなのが書けるようになりますからね(僕はこれいらないと思うけど)
Avatar
例が要らないやつで草
Avatar
Rustのactix-webみたいに引数の型を引っ張ってきてPathParameterにその型を埋め込まないとダメみたいなレベルまでできると嬉しい
3:37 PM
#[get("/{size}/{path:[^{}]+}")] async fn resize( req: HttpRequest, path: web::Path<(String, String)> ) -> impl Responder { こういうの (edited)
Avatar
decl macroの方でできるようになりそう
Avatar
Kishikawa Katsumi 12/14/2022 3:38 PM
これはすごいな。
3:39 PM
新しいキラーWeb Frameworkが作られたりしてほしい。
t_wakaru 1
3:39 PM
Vaporもいいものだけど。
Avatar
なぜかサーバーサイドの人FastAPIみたいな記法好きがちなんだよなわかる
Avatar
Kishikawa Katsumi 12/17/2022 3:21 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0382-expression-macros.md at main · apple/swift-evolution
Avatar
というか、正式レビュー始まりましたよ https://forums.swift.org/t/se-0382-expression-macros/62090
Hello Swift community, The review of SE-0382: "Expression Macros" begins now and runs through December 30, 2022. For context beyond the pitch threads linked in the proposal, there is a prospective vision document which has itself been pitched and is under consideration with the language workgroup. And, as noted in this proposal, a companion p...
Avatar
Kishikawa Katsumi 12/17/2022 3:23 AM
えっ早いね。
3:25 AM
休みに入るためにサンプルリポジトリを大急ぎで用意したんだと思ってた。
Avatar
たしかに、サンプルリポジトリを用意したばっかりだから、練習期間があんまりないですね。レビュー自体は月末までやるみたいだけどw
3:27 AM
3:28 AM
#file#line の型が StaticString , UInt から変わりそうだ。
3:29 AM
<T> で定義してるから従来の line: UInt = #line はこれからもコンパイル通るけど、 line: Int = #line って書けるようになりそう。
Avatar
Kishikawa Katsumi 12/17/2022 3:33 AM
その辺は最終的には全部マクロで再実装されるのかな。
3:33 AM
提案では、やりたそうな感じに見える。
Avatar
We propose to introduce a number of macro declarations into the Swift standard library. There are several different kinds of such macros.
セットで提案みたいですね
Avatar
Kishikawa Katsumi 12/17/2022 3:39 AM
いやー、この状態でレビューするのは難しいだろう。レビューのたびに思うけどみんなすごいな。
Avatar
Kishikawa Katsumi 12/17/2022 4:26 AM
とりあえずXcodeの品質もあって、マクロは使うのも作るのも非常に何が起こってるかわからなくてデバッグしづらい。
4:27 AM
すでに解消されてるコンパイルエラーとかが復活し続けてくるとかですごく難しい。
Avatar
There's a debug dump. Pass -Xfrontend -dump-macro-expansions to the compiler and it'll emit something like this: Macro expansion of #stringify(_:) in /path/to/MacroExamples/MacroExamples/main.swift:6:7-6:24 as (Int, String) ------------------------------ (x + y, "x + y") ------------------------------ Doug
4:30 AM
-Xfrontend -dump-macro-expansions でデバッグできるらしい。
4:30 AM
でもXcodeでいい感じに表示してほしいですね。
4:30 AM
C++でもプリプロセッサを駆使してるやつって展開結果を見ないとなんもわからんのでキツかったりする。
Avatar
Kishikawa Katsumi 12/17/2022 4:35 AM
C++はマクロっぽい機能でテンプレートもあるけど、あれでコンパイルエラーとかはどうやってデバッグするの?
Avatar
あれは超デバッグしにくいです。
4:38 AM
プリプロセッサはプリプロセッサだけ処理した結果を得る方法がある(Xcodeのメニューもある)んですけど
4:38 AM
テンプレートはそれが無いし、 展開後のコードに対する型チェックエラーが出るので、 何がなんだかめっちゃわかりづらいです
4:39 AM
一応テンプレートの実装方法次第で、エラーが早期に出るとかわかりやすく出るとか、そういう工夫はできます。
Avatar
Kishikawa Katsumi 12/17/2022 4:42 AM
なるほど。テンプレートのデバッガとかは無いのか。。。
4:43 AM
Swiftのマクロは使う側はそこまで難しくないと思うけど、Swiftは合法なコードでもコンパイルできない場合があるからそれが起こると大変そうだなと思っている。
4:44 AM
マクロを作る側でできるだけ文を短くするとか型注釈をしっかり書く、みたいなノウハウが出てくると思う。
Avatar
合法なコードでもコンパイルできない場合
Xcodeのバグでリビルドがうまくされないとかのことですか?
Avatar
Kishikawa Katsumi 12/17/2022 4:45 AM
型推論に時間がかかりすぎて、ってやつ。
Avatar
あ〜たしかに。
Avatar
Kishikawa Katsumi 12/17/2022 4:46 AM
今はXcodeのバグもあるね😅直しても直しても同じエラー出るから。
Avatar
Kishikawa Katsumi 12/17/2022 7:28 AM
マクロを提供してメンテナンスしていくことを考えると、SwiftSyntaxのAPIや構文木の使用はある程度固定されてないとまあ困るけどSwiftSyntaxも合わせて正式版になったりするのかな?
Avatar
コンパイラ内部でも使おうとしてるのである程度固定されると思います
Avatar
Kishikawa Katsumi 12/17/2022 7:30 AM
そっちの作業の方が大変そうだな。
Avatar
cxxにブリッジしたりもしてますしね
Avatar
Kishikawa Katsumi 12/17/2022 7:31 AM
でもツリーを辿ってたらいつの間にか知らないNodeが挟まってた、とかはその後も発生するかなあ。
Avatar
追加的な変更はまあ言語仕様と一緒に来ますよね
Avatar
Kishikawa Katsumi 12/19/2022 7:44 AM
そういえばSwiftは5.8を刻むんですね。
Avatar
This post describes the release process, and estimated schedule for Swift 5.8. Snapshots of Swift 5.8 Downloadable snapshots of the Swift 5.8 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 Swift 5.8 is released, th...
7:47 AM
if式やマクロが間に合うならまあまあ目玉リリースになりそうだ。
Avatar
Kishikawa Katsumi 12/19/2022 7:49 AM
そんなに入るかな。Regexあたりが改善されるとかはあるんじゃないかと思うけど。
Avatar
Hello, Swift community! The combined third review of SE-0366: consume operator to end the lifetime of a variable binding and second review of SE-0377: borrow and consume parameter ownership modifiers begins now and run through December 14th, 2022. Throughout the reviews for SE-0366 and SE-0377, reviewers surfaced the concern that ‘take’ is too...
Avatar
Kishikawa Katsumi 12/19/2022 7:52 AM
これは決着つきそう
7:53 AM
名前が決まれば実装はあるからすぐ使えるようになりそう。
Avatar
そうですね。
Avatar
Kishikawa Katsumi 12/26/2022 8:33 AM
https://forums.swift.org/t/pitch-custom-metadata-attributes/62016/46 Custom Metadata属性はもう少し練る必要がありそうだな。Unitテストのテストメソッド発見パターン以外のユースケースがあると良さそうだけど。 RealmみたいなORM的なAPIの構築には便利だと思うけどRealmの人でもこの提案はちょっとその場しのぎに見える、みたいな感じになってる。 (edited)
I think that through compiler evaluation we can unite a lot of features that are currently discussed separately. Both upthread and in the macro threads, forms of static introspection/reflection were discussed. Besides the static guarantee and optimization, I don’t see how that’s different from metadata-based runtime reflections. This feature al...
Avatar
これこそ試しにライブラリを実装してみないと機能の不足とかわかんなそう (edited)
Avatar
Kishikawa Katsumi 12/26/2022 8:38 AM
そうですねえ。Javaや.NETにある類似のライブラリを作ってみるとわかるかな。明らかにそれに影響された機能のようだし。
8:40 AM
https://forums.swift.org/t/pitch-reflection/61438/36 こっちの方はもともとプライベートに使われてたものをAPIとして整理するっていう前提が示されているからかほぼ+1の意見だけどAPIの設計はもっと練ったほうがいいって感じか。
I'm really excited about more introspection capabilities in the language, but after reading the proposal, I think it's missing an important feature, and I don't quite understand another. What I really want to do is be able to find all types in a module (or linked into the app) that conform to a given protocol, and then instantiate instances of ...
Avatar
Swift、別々のモジュールで重複して同じプロトコルに準拠するのはできると思ってたけど、両方 import して呼び分けられるのか。 // ModuleA extension Int: Sequence { public func makeIterator() -> IndexingIterator<[Int]> { [self].makeIterator() } } // ModuleB import struct Foundation.Data extension Int: Sequence { public func makeIterator() -> Data.Iterator { var value = self return Data(bytes: &value, count: MemoryLayout.size(ofValue: value)).makeIterator() } } // main.swift import ModuleA import ModuleB let n = 65534 for x: Int in n { print(x) } for x: UInt8 in n { print(x) } https://github.com/koher/extension-collision-swift (edited)
Avatar
omochimetaru 1/8/2023 10:20 AM
これ実装がたまたまそうなってオーバーロード解決してる+静的な解決だからそのように動いてる、だけじゃないかしら・・・?
10:21 AM
ランタイムでグローバルに一個しか、ある型TのPへのconformは登録できないという認識で、ダイナミックなケースだとうまくいかないと思います
Avatar
omochimetaru 1/8/2023 10:30 AM
1枚目と2枚目: importするモジュールによって片方がエラー 3枚目: 両方importすると片方がエラー
10:31 AM
↑この例だと、2つインポートした場合は、片方のconformanceは無かった事になっているとみなせると思います。
10:33 AM
ただこれは半分ダイナミックなケースですね。 ジェネリック関数を呼び出すところでダイナミックなABIを通すけど、その前の型検査は静的にやっているので。 完全にダイナミックなケース(Any からキャストする)を実験しようとしたんですが、associatedtypeを具象型に含めてキャストするのって今はできない気がする?
10:33 AM
as? any Sequence<Int> が書けたらいいんですけど
10:34 AM
自分のマシンがMontreryだからまだできないかも (edited)
Avatar
import ModuleA しかしないファイルで x: Int に対して x.makeIterator() と書くと "Ambiguous use of makeIterator()" と怒られました。 (edited)
10:35 AM
1枚目と2枚目: importするモジュールによって片方がエラー
ですら型推論で判別されていて、 import で判別されているわけではない?
Avatar
Avatar
koher
import ModuleA しかしないファイルで x: Int に対して x.makeIterator() と書くと "Ambiguous use of makeIterator()" と怒られました。 (edited)
omochimetaru 1/8/2023 10:41 AM
ホントだ・・・ あ、でも、 useA.swift の中身もコメントアウトして、ExtensionCollision の中に import ModuleA が全くない状態にしたら、ambiguousが消えました。
10:42 AM
<T: Sequence> な関数への適用はそのファイルの import 文が解決に影響するけど、直接の .makeIterator() の呼び出しは、モジュール全体での import が関係するみたいですね・・・?
Avatar
// ModuleC public func show<S: Sequence>(_ sequence: S) where S.Element: AdditiveArithmetic { for x in sequence { print(x) } } import ModuleA import ModuleC func useA(for x: Int) { x.foo() show(x) } import ModuleB import ModuleC func useB(for x: Int) { x.foo() show(x) } // main.swift import ModuleA import ModuleB useA(for: 65534) useB(for: 65534) ↑、 main の import 書く順によってどっちが呼び出されるか変わる😂
Avatar
Avatar
omochimetaru
<T: Sequence> な関数への適用はそのファイルの import 文が解決に影響するけど、直接の .makeIterator() の呼び出しは、モジュール全体での import が関係するみたいですね・・・?
↑のパターンも出てきたからカオス。 ambiguous になるパターン、型から一つが選ばれるパターン、よくわからないルールで一方が選ばれるパターン。
Avatar
omochimetaru 1/8/2023 10:56 AM
よくわからないルールはコンパイラが生成するビルド処理でたまたま並んだ順番とかで決まってそう
Avatar
そうですね。
10:56 AM
多分そんな感じ。 (edited)
Avatar
omochimetaru 1/8/2023 10:56 AM
main.swift のほうがアルファベット順で上だからそのファイルの import文に支配されてるのかも。
Avatar
うん、その可能性あるとも思ってる。
10:57 AM
エントリーポイントから処理されてる可能性もあるかもだけど。
10:57 AM
main.swift から import 消したら ModuleA が優先されたから、ファイル名順で useA.swift が優先された可能性も高そう。
Avatar
omochimetaru 1/8/2023 10:59 AM
今回の例みたいに
11:00 AM
型 T と プロトコル P において、それらが定義されたモジュールとは別のモジュールで、 T: P を後付準拠(retroactive conformance)させるのは、 それを利用ライブラリAとアプリBの2箇所でやってしまったりしているとこのように崩壊するので
11:00 AM
コンパイラが警告を出すようにしよう、という提案が出てますね https://forums.swift.org/t/returned-for-revision-se-0364-warning-for-retroactive-conformance-of-external-types/59729
The review of SE-0364: Warning for Retroactive Conformance of External Types ran from July 13th to 27th. The language workgroup has decided to accept in principle that a warning should be added for such conformances, but we are returning the proposal for revision to explore what the mechanism of silencing the warning should be. Accepted princip...
11:01 AM
8月で審査が再検討になってから止まってるな。
Avatar
そっかー。 import で切り替えられたらグローバルな汚染を気にせず extension で準拠させられるんだけどなぁ。
11:02 AM
コールスタックを考えると一意に定まる気がするけど、実行時のパフォーマンスに影響を与えずには無理そうかな。 (edited)
Avatar
omochimetaru 1/8/2023 11:05 AM
Ventura以降なら、一度 Any 型の変数に入れてから、 anySeq as? any Sequence<Int> でダウンキャストしてから implicit open で <T: Sequence> where T.Element == Int に変換するパターンのコードが書けて、これはコールスタックとかで静的に決められないですね。
11:06 AM
静的なケースで <T: Sequence> where T.Element == Int> な引数を受け取る関数をネストして呼び出すパターンのコードなら、内側の呼び出しでは、外側の関数が受け取ったwitness tableをリレーしていくコードになるので、一貫性を維持して呼び出しが潜っていくはず。
Avatar
any は確かに厳しそう・・・
Avatar
omochimetaru 1/8/2023 11:07 AM
その場合に限っては呼び出し元のファイルのimport文とかでちゃんと扱えてもいいかもしれないけど、その内部の奥底で グローバル変数の Any 型にコピーしちゃうケースとかを考えると結局怪しい動作にはつながる。
Avatar
any を介しても existential containerがwitness table保持してるし、openされたときもそれが選択されたらうまくいかないかな?
Avatar
omochimetaru 1/8/2023 11:10 AM
any Sequence ならそうですね。 > witness tableを引き回す でも Any はwitness tableを持たないので、Any から as? any Sequence<Int> は不安定です。 (edited)
Avatar
なるほど、 Any か。
Avatar
Kishikawa Katsumi 1/9/2023 5:29 PM
https://forums.swift.org/t/se-0382-expression-macros/62090/22 マクロでStringのバイト列を直接埋め込むってのはおもしろい。 あとちょいちょい反対意見も出てきた。 レビューチームとしては使ってみてユースケースに対して仕様の不足がないかみてほしいと考えてるらしい。
Would expression macros support trailing closure syntax? I have the feeling that passing closures could be a major use-case.
Avatar
Kishikawa Katsumi 1/10/2023 12:55 AM
リテラルを渡す場合に限るけどマクロを使うと値の範囲をコンパイル時にチェックしたり特定のパターンに一致しない文字列をエラーにしたりできるな。なんかの役に立つかしら?
Avatar
omochimetaru 1/10/2023 1:07 AM
@swift-main let a: Int8 = 80 + 80
Avatar
Avatar
omochimetaru
@swift-main let a: Int8 = 80 + 80
swiftNightly BOT 1/10/2023 1:07 AM
exit status: 1 with stderr:<stdin>:1:18: error: arithmetic operation '80 + 80' (on type 'Int8') results in an overflow let a: Int8 = 80 + 80 ~~ ^ ~~
Avatar
omochimetaru 1/10/2023 1:07 AM
↑こういうのはコンパイラにすでにありますね
1:07 AM
理屈上はそういうコンパイル時の定数計算(+検査)みたいなものはマクロである程度代用できますね。 (edited)
1:08 AM
昔だったら正規表現が正規表現文法に違反してる、とかもコンパイル時チェックする需要があったと思う。 今はRegexがまさにそれやってくれるけど
Avatar
Kishikawa Katsumi 1/10/2023 2:02 AM
このチェックは型の範囲内かどうかだから例えば50〜100の間、とか100以下とかUUIDの形式、とかは役に立ちそうかなって。
2:03 AM
配列で要素数がn個とか。
Avatar
omochimetaru 1/10/2023 4:57 AM
たしかにマクロにnとかの引数もあたえることで新しい検査ができますね
4:58 AM
Build-Time Constant Values Authors: Artem Chikin, Ben Cohen, Xi Ge Introduction A Swift language feature for requiring certain values to be knowable at compile-time. This is achieved through an attribute, @const, constraining properties and function parameters to have compile-time knowable values. Such information forms a foundation for rich...
4:59 AM
そういうのは多分コンパイル時計算のほうがマッチしていると思うけど、 これはピッチから進んでないからなあ。
Avatar
Kishikawa Katsumi 1/10/2023 6:40 AM
https://forums.swift.org/t/se-0359-build-time-constant-values/57562 レビューに入ったあと差し戻しになったみたいよ。
Hello Swift community, The review of SE-0359 "Build-Time Constant Values" begins now and runs through June 6, 2022. 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...
Avatar
omochimetaru 1/10/2023 6:59 AM
なるほど
Avatar
omochimetaru 1/10/2023 3:20 PM
An initial implementation for member declaration macros. Member declaration macros are represented as custom attributes, and expanding a member macro for a given declaration can produce a set of ne...
3:21 PM
式マクロとは別のメンバ生成マクロの実装が来た
Avatar
omochimetaru 1/10/2023 3:30 PM
structの中で使ってプロパティを生成する例の他に、トップレベルで使って型を生成してるのがあるな
Avatar
Kishikawa Katsumi 1/10/2023 8:15 PM
これは記法で議論がありそうだな。さすがにこの例は何が起こるのかわからなさすぎる。
Avatar
public let testMacros: [String: Macro.Type] = [ "checkContext": CheckContextIndependenceMacro.self, "colorLiteral": ColorLiteralMacro.self, "fileID": FileIDMacro.self, "imageLiteral": ImageLiteralMacro.self, "stringify": StringifyMacro.self, "myError": ErrorMacro.self, "bitwidthNumberedStructs": DefineBitwidthNumberedStructsMacro.self, "addCompletionHandler": AddCompletionHandler.self, "addBackingStorage": AddBackingStorage.self, ]
11:32 PM
public struct AddBackingStorage: MemberDeclarationMacro { public static func expansion( of node: CustomAttributeSyntax, attachedTo decl: DeclSyntax, in context: inout MacroExpansionContext ) throws -> [DeclSyntax] { let storage: DeclSyntax = "var _storage: Storage<Self>" return [ storage.withLeadingTrivia([.newlines(1), .spaces(2)]) ] } }
11:32 PM
これだけか
11:35 PM
varが生えるとかstructが生えるとかがノーヒントなのは、型定義がある式マクロと比べるとわかりにくい
11:36 PM
しかし、「何が起きるのかわかるように宣言する」機能と、「マクロでなんでもできる」性質は矛盾するから仕様のバランスが難しそうだなあ
Avatar
Kishikawa Katsumi 1/10/2023 11:38 PM
SwiftSyntaxがもうちょっと簡単になったら読めばわかるでもいいけどね。
Avatar
A set of Swift libraries for parsing, inspecting, generating, and transforming Swift source code. - swift-syntax/MacroSystemTests.swift at f5f45e224c4d12403e96dcf50c4d59fbdccf070d · apple/swift-syntax
Avatar
Kishikawa Katsumi 1/10/2023 11:41 PM
フォーラムの議論にの方にもちょっとあったけどTriviaを意識しないといけないとかもかなり読みにくくしてるんよな。
Avatar
AddCompletionHandler はパッと見だいぶ難しい
11:42 PM
指定された func を元に、completion handlerを持つ版の func を生成する(func1個が2個に増殖する)
Avatar
Kishikawa Katsumi 1/10/2023 11:42 PM
Triviaをちゃんと保持して付け足さないとコンパイルエラーになったりするのは勝手にうまいことやってほしい、みたいに思っている。
Avatar
Triviaムズいですよね
11:43 PM
その代わり、コメントや改行まで正確にコントロールできるのがメリットですけど・・・
Avatar
Kishikawa Katsumi 1/10/2023 11:43 PM
Parseしてそれを使うぶんにはいい仕組みなんだけど改変する場合に相性が良くないんすよね。
Avatar
あと僕が触って難しかったのは関数呼び出しの引数を区切るカンマの管理。 (edited)
11:44 PM
気持ちとしては関数呼び出しと引数リストにしか興味ないけど、syntaxレベルのAPIだからカンマ区切りの面倒をみないといけない (edited)
Avatar
Kishikawa Katsumi 1/10/2023 11:44 PM
SwiftSyntaxのASTはソースコードに忠実すぎてあんまり構造として扱っているという感じじゃない。 (edited)
Avatar
Avatar
Kishikawa Katsumi
SwiftSyntaxのASTはソースコードに忠実すぎてあんまり構造として扱っているという感じじゃない。 (edited)
それがまさに AST じゃなくて CST だからですねえ Abstractじゃない。
Avatar
Kishikawa Katsumi 1/10/2023 11:45 PM
やっぱりもう一段階抽象化されたラッパーがいるよね。
Avatar
Triviaに対して「いい感じにしといて」みたいな特殊な値が設定できたらいいのかなあ?
Avatar
Avatar
Kishikawa Katsumi
やっぱりもう一段階抽象化されたラッパーがいるよね。
そうですね。意味的な構造だけabstractに操作する方法がほしいですね。どういうふうなAPIならうまく共存できるかイメージついてないけど
Avatar
Kishikawa Katsumi 1/10/2023 11:47 PM
リフレクションのAPIみたいな感じのが私はいいと思う。
Avatar
たしかにあの粒度は意味情報だけになってそう
Avatar
Kishikawa Katsumi 1/10/2023 11:49 PM
特に今回の宣言につけられるマクロとか将来的に関数につけられるマクロが出てきたときに、 addInstanceVariableとか、returnStatement.insertBefore()みたいなインターフェースがあると使いやすいと思う。
Avatar
なるほど。
Avatar
Kishikawa Katsumi 1/10/2023 11:51 PM
今のSwiftSyntaxだとリターン文の前にprint()を入れる、っていうのもreturnを見つけて、前後を見て壊さないようにコードを挿入する、っていう手続きになって、かなり冗長になりそう (edited)
Avatar
omochimetaru 1/11/2023 7:53 AM
Hey all, SE-0382 "Expression Macros" is under review now. Expression macros are one piece of the larger vision for macros. Declaration macros are another pieces, and are quite possibly the most important one, because they provide the ability for macros to produce new declarations as well as augment existing declarations. Declaration macros sup...
7:54 AM
見逃してた、ここだ (edited)
Avatar
omochimetaru 1/11/2023 7:34 PM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/nnnn-declaration-macros.md at declaration-macros · DougGregor/swift-evolution
7:34 PM
decl macroは色んなカテゴリが定義されていて、それで何が起きるかなんとなくわかるみたいだ
7:38 PM
witness decl macroとか、peerマクロとaccessorマクロによるClamping property wrapperの置き換えの例が面白い
Avatar
Kishikawa Katsumi 1/14/2023 5:43 AM
例に出てるasyncメソッドにマクロを付けるとコールバックを受け取る関数を自動的に生成するっていうのはよいな。そういう機械的なボイラープレート、SwiftUIを使うときによさそう。
5:48 AM
@declaration(body) macro traced(logLevel: Int = 0) こんな感じでどこに作用するマクロなのかを宣言で指定するからキレイに作ってあればそれでなんとなくわかるし、ソースコード読むことになっても手がかりになるということか。
Avatar
omochimetaru 1/14/2023 5:49 AM
ですね~
Avatar
Kishikawa Katsumi 1/14/2023 5:52 AM
Dougさんは以下のマクロを実装するのは簡単だし読む場合も明らかと言ってるけどそこはだいぶ見解の相違がありそうだな。 public struct AddCompletionHandler: PeerDeclarationMacro { public static func expansion( of node: CustomAttributeSyntax, attachedTo declaration: DeclSyntax, in context: inout MacroExpansionContext ) throws -> [DeclSyntax] { // Only on functions at the moment. We could handle initializers as well // with a bit of work. guard let funcDecl = declaration.as(FunctionDeclSyntax.self) else { throw CustomError.message("@addCompletionHandler only works on functions") } // This only makes sense for async functions. if funcDecl.signature.asyncOrReasyncKeyword == nil { throw CustomError.message( "@addCompletionHandler requires an async function" ) } // Form the completion handler parameter. let resultType: TypeSyntax? = funcDecl.signature.output?.returnType.withoutTrivia() let completionHandlerParam = FunctionParameterSyntax( firstName: .identifier("completionHandler"), colon: .colonToken(trailingTrivia: .space), type: "(\(resultType ?? "")) -> Void" as TypeSyntax ) // Add the completion handler parameter to the parameter list. let parameterList = funcDecl.signature.input.parameterList let newParameterList: FunctionParameterListSyntax if let lastParam = parameterList.last { // We need to add a trailing comma to the preceding list. newParameterList = parameterList.removingLast() .appending( lastParam.withTrailingComma( .commaToken(trailingTrivia: .space) ) ) .appending(completionHandlerParam) } else { newParameterList = parameterList.appending(completionHandlerParam) } let callArguments: [String] = try parameterList.map { param in guard let argName = param.secondName ?? param.firstName else { throw CustomError.message( "@addCompletionHandler argument must have a name" ) } if let paramName = param.firstName, paramName.text != "_" { return "\(paramName.withoutTrivia()): \(argName.withoutTrivia())" } return "\(argName.withoutTrivia())" } let call: ExprSyntax = "\(funcDecl.identifier)(\(raw: callArguments.joined(separator: ", ")))" // FIXME: We should make CodeBlockSyntax ExpressibleByStringInterpolation, // so that the full body could go here. let newBody: ExprSyntax = """ Task { completionHandler(await \(call)) } """ // Drop the @addCompletionHandler attribute from the new declaration. let newAttributeList = AttributeListSyntax( funcDecl.attributes?.filter { guard case let .customAttribute(customAttr) = $0 else { return true } return customAttr != node } ?? [] ) let newFunc = funcDecl .withSignature( funcDecl.signature .withAsyncOrReasyncKeyword(nil) // drop async .withOutput(nil) // drop result type .withInput( // add completion handler parameter funcDecl.signature.input.withParameterList(newParameterList) .withoutTrailingTrivia() ) ) .withBody( CodeBlockSyntax( leftBrace: .leftBraceToken(leadingTrivia: .space), statements: CodeBlockItemListSyntax( [CodeBlockItemSyntax(item: .expr(newBody))] ), rightBrace: .rightBraceToken(leadingTrivia: .newline) ) ) .withAttributes(newAttributeList) .withLeadingTrivia(.newlines(2)) return [DeclSyntax(newFunc)] } }
Avatar
Avatar
Kishikawa Katsumi
Dougさんは以下のマクロを実装するのは簡単だし読む場合も明らかと言ってるけどそこはだいぶ見解の相違がありそうだな。 public struct AddCompletionHandler: PeerDeclarationMacro { public static func expansion( of node: CustomAttributeSyntax, attachedTo declaration: DeclSyntax, in context: inout MacroExpansionContext ) throws -> [DeclSyntax] { // Only on functions at the moment. We could handle initializers as well // with a bit of work. guard let funcDecl = declaration.as(FunctionDeclSyntax.self) else { throw CustomError.message("@addCompletionHandler only works on functions") } // This only makes sense for async functions. if funcDecl.signature.asyncOrReasyncKeyword == nil { throw CustomError.message( "@addCompletionHandler requires an async function" ) } // Form the completion handler parameter. let resultType: TypeSyntax? = funcDecl.signature.output?.returnType.withoutTrivia() let completionHandlerParam = FunctionParameterSyntax( firstName: .identifier("completionHandler"), colon: .colonToken(trailingTrivia: .space), type: "(\(resultType ?? "")) -> Void" as TypeSyntax ) // Add the completion handler parameter to the parameter list. let parameterList = funcDecl.signature.input.parameterList let newParameterList: FunctionParameterListSyntax if let lastParam = parameterList.last { // We need to add a trailing comma to the preceding list. newParameterList = parameterList.removingLast() .appending( lastParam.withTrailingComma( .commaToken(trailingTrivia: .space) ) ) .appending(completionHandlerParam) } else { newParameterList = parameterList.appending(completionHandlerParam) } let callArguments: [String] = try parameterList.map { param in guard let argName = param.secondName ?? param.firstName else { throw CustomError.message( "@addCompletionHandler argument must have a name" ) } if let paramName = param.firstName, paramName.text != "_" { return "\(paramName.withoutTrivia()): \(argName.withoutTrivia())" } return "\(argName.withoutTrivia())" } let call: ExprSyntax = "\(funcDecl.identifier)(\(raw: callArguments.joined(separator: ", ")))" // FIXME: We should make CodeBlockSyntax ExpressibleByStringInterpolation, // so that the full body could go here. let newBody: ExprSyntax = """ Task { completionHandler(await \(call)) } """ // Drop the @addCompletionHandler attribute from the new declaration. let newAttributeList = AttributeListSyntax( funcDecl.attributes?.filter { guard case let .customAttribute(customAttr) = $0 else { return true } return customAttr != node } ?? [] ) let newFunc = funcDecl .withSignature( funcDecl.signature .withAsyncOrReasyncKeyword(nil) // drop async .withOutput(nil) // drop result type .withInput( // add completion handler parameter funcDecl.signature.input.withParameterList(newParameterList) .withoutTrailingTrivia() ) ) .withBody( CodeBlockSyntax( leftBrace: .leftBraceToken(leadingTrivia: .space), statements: CodeBlockItemListSyntax( [CodeBlockItemSyntax(item: .expr(newBody))] ), rightBrace: .rightBraceToken(leadingTrivia: .newline) ) ) .withAttributes(newAttributeList) .withLeadingTrivia(.newlines(2)) return [DeclSyntax(newFunc)] } }
omochimetaru 1/14/2023 5:53 AM
Dougさん基準w
Avatar
Kishikawa Katsumi 1/14/2023 5:53 AM
> Removing the need for the trivia manipulation would probably help quite a bit with that too; if you're used to looking at code using SwiftSyntax I assume your eyes just automatically skip all of the withoutTrivia() etc. calls, but for someone new to it that's a lot of extra incidental code to read on the way to understanding what's actually happening. Definitely. I probably spent a quarter of my time on this messing with trivia 🙂. It's something we can improve on via the swift-syntax APIs over time.
ただまあこの辺が冗長になるということは伝わってるらしい。
(edited)
Avatar
omochimetaru 1/14/2023 5:55 AM
おお。いい感じのAPIつけてほしい
Avatar
Kishikawa Katsumi 1/14/2023 5:56 AM
Property Wrappersとマクロが重なる部分があるのでどっちを使うか、という話が出てきそうだけどProperty Wrappersはデバッグしやすいし見えない部分はないからその点でProperty Wrappersかな。 マクロのデバッグサポートがめっちゃ使いやすかったら別だけど。
5:57 AM
今のところ作るのも使うのもProperty Wrappersの方がだいぶ簡単だろう。
Avatar
omochimetaru 1/20/2023 5:33 PM
Hey all, It's become very clear to me that this "declaration macros" pitch is really two separate proposals rolled into one, so I've gone ahead and split this document into two separate proposals that we can iterate on: Freestanding macros covers the "freestanding" case, generalizing the # syntax to also introduce declarations and code items...
5:34 PM
decl macroがattached macroとfreestanding macroに分かれた (edited)
Avatar
Kishikawa Katsumi 1/20/2023 5:45 PM
妥当だと思う。Declaration macrosは式マクロ以外の残りのアイデア全部入れたって感じだったから。 (edited)
5:46 PM
分けて個別にやったほうが議論もしやすそう。
Avatar
Avatar
Kishikawa Katsumi
分けて個別にやったほうが議論もしやすそう。
omochimetaru 1/20/2023 5:46 PM
ですねー
Avatar
The review of SE-0380: if and switch expressions ran from December 7th to December 30th. Feedback was generally positive; many reviewers noted that the usability of if expressions in other languages is missed in Swift, and selection statements producing a single value in each branch is a common pattern across their Swift code. Most of the discus...
11:04 PM
if / switch 式内の return はなしで accepted になったみたいですね
Avatar
omochimetaru 1/21/2023 2:26 AM
attached macroはpeer, accessor, member, memberAttribute macroの4つにしぼられてるな body, conforming, witnessは切り離されてる
2:26 AM
Here are several possibilities, omitted from this proposal primarily to reduce scope.
2:33 AM
-- freestanding macroの方も見てるけど
Additionally, we replace the @expression attribute introduced in SE-0382 with @freestanding(expression)
(edited)
2:33 AM
@expressionが産まれる前にオワコンかもしれん
Avatar
Kishikawa Katsumi 1/21/2023 3:53 AM
まあそもそもそこは人間が読むためのもののはずだから区別できればなんでもいいんじゃなかったかな。たしかなくてもいいやつ。
Avatar
omochimetaru 1/21/2023 3:53 AM
それはそうですね。
Avatar
Kishikawa Katsumi 1/21/2023 4:01 AM
正直なくていいならややこしいのいらんと思うんですけどね。
Avatar
omochimetaru 1/21/2023 4:22 AM
コード中のどこに書けるかを規定しているので無くすことはできないと思います
Avatar
Kishikawa Katsumi 1/21/2023 5:29 AM
でもExpression macroはExpressionMacroプロトコルだしどのプロトコルかでわかるんじゃないかな。
Avatar
omochimetaru 1/21/2023 6:15 AM
たしかに。わざわざ手でヘッダー書いてるみたいな感じもありますね
Avatar
Hello, Swift community. The review of SE-0386: package Access Modifier begins now and runs through February 8th, 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 by email. When contact...
👀 1
12:27 AM
packageスコープの審査だそうです (edited)
12:27 AM
他の案のところみると_spiの正式仕様版なのかな
Avatar
パッケージ単位の最適化が行われるようになる?たとえば、 package class Foo がパッケージ内で継承されていなければ静的ディスパッチにできるとか。
12:36 AM
それがされるなら、ついでに同一パッケージだとモジュールを越えて Specialize されるようになったりしないかな?
Avatar
inlineableってBUILD_LIBRARY_FOR_DISTRIBUTIONでは使えないですけど、packageスコープだったら使えるようになったりしないかな
Avatar
packageスコープでも同一パッケージからサブクラスできるかどうかは保留されてるっぽい? (edited)
12:58 AM
ただpublic未満にできることで増える最適化機会はいろいろありそうですね
Avatar
Avatar
Iceman
inlineableってBUILD_LIBRARY_FOR_DISTRIBUTIONでは使えないですけど、packageスコープだったら使えるようになったりしないかな
パッケージ単位の最適化が働くなら、 inlinable 関係なくパッケージ内はインライン化できそう。
Avatar
inlineableあるとxcframeworkとして出荷できなくなるんですけど、その制約を既存の機能保ったまま取っ払えると嬉しい。
Avatar
Kishikawa Katsumi 1/28/2023 11:20 AM
https://github.com/apple/swift/pull/62425 Xcodeの右クリックからマクロを展開できるようになる、、、のかな?
Add refactoring "Expand Macro" that expands macro expressions. rdar://102739026
Avatar
テストの書き方が特殊でよくわからないけど多分そうかな? // EXPAND: source.edit.kind.active: // EXPAND-NEXT: 4:7-4:24 "(a + b, "a + b")" (edited)
Avatar
Kishikawa Katsumi 1/28/2023 11:25 AM
だいぶいいよね。コンパイルエラーの表示も追従してくれるかな?
Avatar
保守する上ではマクロ式のままがいいから、生成結果の確認とかコンパイルエラーの確認のために展開してみて、オッケーだったらCmd+Zでもとに戻すみたいな?
Avatar
Kishikawa Katsumi 1/28/2023 11:25 AM
GitのDiffみたいなインライン表示のUIにならないかな。Refactorメニューだからテキストを変更しちゃうんだろうか。
11:26 AM
RegexのResult Builderに変換、みたいになるってことか。
Avatar
実際にテキストに展開する機能な気がしますね。 あってもいいし使い所はあるけど、一番欲しいのはポップアップで一時的な感じで見える方だなあ
Avatar
Kishikawa Katsumi 1/28/2023 11:29 AM
そういえばマクロが生成したコードは展開した後の結果を使ってコード補完されるのかな。 別モジュールに分かれてる場合は補完されるだろうけど同じモジュール内の場合も補完してくれるんだろうか。 (edited)
Avatar
それちょっと気になってるんですよねー 展開した後の結果を使わないと、メソッドとか生えてなくて無理だと思います
Avatar
Kishikawa Katsumi 1/28/2023 12:00 PM
聞いてみよ。メンバ変数、関数生成系は補完に出ないと使いづらい。 (edited)
Avatar
りゅーせい 1/29/2023 11:54 PM
質問です。画面をtransformして0.9に小さくする処理を書いてるのですが、headerも小さくする方法ってないですか?
11:56 PM
画面遷移した際に、透過した親viewのサイズをtransformで変えているのですが、navigationControllerだけ変わらなくて、やり方分からなくて困ってます。
Avatar
りゅーせい 1/30/2023 5:29 AM
↑すみませんこちらの問題は解決したのですが、navigationbarに動的に制約を設定する方法だけ誰かご存知でないでしょうか?
Avatar
質問は #beginner-help-archived がオススメです navigationbarをどうしたいのかが解らないのでなんともですが、パッと思い付く方法だとchildViewControllerにUINavigationControllerを追加して、UINavigationController.viewに対して制約を追加するのが手っ取り早いでしょうか?
Avatar
Avatar
tarunon
質問は #beginner-help-archived がオススメです navigationbarをどうしたいのかが解らないのでなんともですが、パッと思い付く方法だとchildViewControllerにUINavigationControllerを追加して、UINavigationController.viewに対して制約を追加するのが手っ取り早いでしょうか?
りゅーせい 1/30/2023 7:03 AM
わかりました!そちらで質問してみます! ありがとうございます🙇‍♂️ 簡単にいうとtransformしたnavigationBarを中央に持ってきたいのですが、直接navigationBarに制約を設定してもびくともしないという感じです。
Avatar
@objc public protocol A: AnyObject { @objc var name: String { get } } 例えばこういうのが Swift なモジュールにあって、それを @interface B : NSObject <A> @end こんな感じで Objective-C なモジュールから使って、それを func f() { let b = B() print(b.name) } こうやって Swift なモジュールから使うと、nameが見えないと言われる。 でも、 func f() { let b: A = B() print(b.name) } こうすると問題なく使える。 (edited)
6:11 AM
何が起こっているんだ...
Avatar
壊れてそう、全部swiftなら問題ないですよね
Avatar
もちろんです
6:13 AM
A が Objective-C ならもちろん問題ない
6:18 AM
いったいなにが...
Avatar
I wonder why this is happening. Contribute to niw/SwiftObjcProtocolBridgeTest development by creating an account on GitHub.
6:41 AM
ちょっと再現セットアップがめんどい
Avatar
Kishikawa Katsumi 2/3/2023 5:20 AM
https://forums.swift.org/t/returned-for-revision-se-0382-expression-macros/62898 マクロの仕様レビューも周辺を巻き込んで大きくなっていく感じなのかな?
The review of SE-0382: Expression Macros ran from December 16, 2022 until January 15, 2023. Overall, the feedback we received was positive. Modifications were incorporated to the proposal during review based on early feedback when the review period was extended. Having reviewed all of the points raised during the review period, the language wor...
Avatar
Avatar
Kishikawa Katsumi
Swiftのマクロ、ファイルが読めるならバイナリをソースコードに埋め込む、っていうのできそうだけどファイル読めるかなあ。
SwiftPMのほうにファイルを埋め込む機能がきてますね https://github.com/apple/swift-package-manager/pull/6067
Basic support for a new .embed resource rule which will allow embedding the contents of the resource into the executable code by generating a byte array, e.g. @_implementationOnly import struct Fou...
4:34 AM
毎回ファイル読み込んでコード生成する形なので依存解決とかは問題なさそうだけど、ビルドの効率は悪そう?
Avatar
omochimetaru 2/9/2023 4:44 AM
キャッシュが効けば平気そう
Avatar
ファイルが大きいときにSwiftPMがコード生成する時間とswiftcがパースとかする時間が効率悪そうという意味でした。PRのFIXMEにも書かれてますが。
Avatar
Kishikawa Katsumi 2/9/2023 4:57 AM
良さそうだ。確かにSwiftPMがやってくれるならそれがベターな気がする。
Avatar
Avatar
Iceman
ファイルが大きいときにSwiftPMがコード生成する時間とswiftcがパースとかする時間が効率悪そうという意味でした。PRのFIXMEにも書かれてますが。
omochimetaru 2/9/2023 5:00 AM
1回目はそうですね。バイナリがわざわざリテラル表現になっちゃうし。
Avatar
Kishikawa Katsumi 2/9/2023 5:07 AM
ビルドツールでやるんならコード生成じゃなくてそのままくっつけてなんかうまいこと参照するとかできないんかな。
Avatar
Hello everyone, I'd like to share the first pitch exploring the realms of custom executors in Swift. This proposal focuses on the minimum viable pieces to make actor executors configurable by library authors or end-users. It is based on the early draft of custom executors by @John_McCall which we had shared way back when Swift Concurrency was...
11:26 PM
Custom Executorのドラフト出てる
11:27 PM
まだ入ってないmoveonly typeがある想定で書かれてmoveonly struct Jobというのが出てくる。
Avatar
moveonlyにすることで同じJobを2回実行しないようにしているんですね。
👉 1
Avatar
omochimetaru 2/17/2023 5:44 PM
Hello Swift community, The review of SE-0389: "Attached Macros" begins now and runs through March 2, 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 ...
5:46 PM
Attached macro審査
Avatar
まだWIPですけどObservationの実装出てきましたね。swift-async-algorithmにあったCritical Regionを作る仕組みとかを持ってきているようですね👀 https://github.com/apple/swift/pull/63725 (edited)
This is an initial draft of the observation feature. It includes an implementation of the Observation module and associated protocols and utility types. This does not yet include the macro synthesi...
Avatar
Avatar
shiz
まだWIPですけどObservationの実装出てきましたね。swift-async-algorithmにあったCritical Regionを作る仕組みとかを持ってきているようですね👀 https://github.com/apple/swift/pull/63725 (edited)
Observable関連の型とかライブラリの部分かな? 特定の型を購読可能にする部分は含まれてなさそう?
Avatar
Avatar
omochimetaru
Observable関連の型とかライブラリの部分かな? 特定の型を購読可能にする部分は含まれてなさそう?
Observable関連の型とかライブラリの部分かな?
はい、そうです。
特定の型を購読可能にする部分は含まれてなさそう?
ObservationRegistarですかね? https://github.com/apple/swift/pull/63725/files#diff-b824e8d6f2a9d4c217d42ac8ef67d7628dafda2e86321ac23c4dc2e90545f13b
Avatar
Avatar
shiz
Observable関連の型とかライブラリの部分かな?
はい、そうです。
特定の型を購読可能にする部分は含まれてなさそう?
ObservationRegistarですかね? https://github.com/apple/swift/pull/63725/files#diff-b824e8d6f2a9d4c217d42ac8ef67d7628dafda2e86321ac23c4dc2e90545f13b
プロパティの変更時にイベントを発火する処理の部分です type wrapperかマクロが必要な部分。
Avatar
Avatar
omochimetaru
プロパティの変更時にイベントを発火する処理の部分です type wrapperかマクロが必要な部分。
💦 まだなさそうです。 (edited)
Avatar
Avatar
shiz
💦 まだなさそうです。 (edited)
そこがどうなるかに一番興味があります
👍🏻 1
Avatar
Avatar
omochimetaru
そこがどうなるかに一番興味があります
追加情報出てきたら共有します!
😍 1
Avatar
omochimetaru 2/22/2023 2:57 AM
Hello Swift community, The review of SE-0390: "@noncopyable structs and enums" begins now and runs through March 7, 2023. This feature is already partially implemented on the main branch of Swift behind the -enable-experimental-move-only flag. There are some pieces that landed very recently and are therefore not yet available in the normal ni...
2:57 AM
moveonly typeの審査が来ました!
2:58 AM
@noncopyable struct FileDescriptor { private var fd: Int32 init(fd: Int32) { self.fd = fd } func write(buffer: Data) { buffer.withUnsafeBytes { write(fd, $0.baseAddress!, $0.count) } } deinit { close(fd) } }
2:58 AM
moveonly じゃなくて @noncopyable というアトリビュートになったらしい。 (edited)
Avatar
c++感あるw
Avatar
omochimetaru 2/22/2023 7:38 AM
ざっと読んで来たけど
7:38 AM
コピーができないから普通のValue Semanticsが使えないのでジェネリックパラメータにハメることができない、というのがキツすぎる
7:38 AM
その結果、Optionalに入れることもできないって。
7:40 AM
ワークアラウンドとか書いてあるけど、将来の方向性として、moveonlyを絡めたconditionalなジェネリクスとか書いてあるけど、最初からないとつらそー (edited)
Avatar
これ var let の延長として、 moveonlyで値を宣言する、みたいな方向性じゃないのか (edited)
7:46 AM
値の宣言時に定義できるなら、genericsの問題も発生しないし、ArrayもOptionalも使えるように思う。それで破綻が産まれるかは、考えてはないけど
Avatar
Avatar
tarunon
これ var let の延長として、 moveonlyで値を宣言する、みたいな方向性じゃないのか (edited)
omochimetaru 2/22/2023 7:48 AM
deinit書けるところとか大事だからユースサイトではうまく行かないと思う
Avatar
ふむー
Avatar
コピー可能かどうかがモジュール内部でしか見えないプロパティに埋まってしまうと、letで受けれるかどうか判断できなくなりそうですね
Avatar
Avatar
Iceman
コピー可能かどうかがモジュール内部でしか見えないプロパティに埋まってしまうと、letで受けれるかどうか判断できなくなりそうですね
omochimetaru 2/22/2023 7:51 AM
それは型宣言についてるから外からもわかるはず ちなみにletでは常に受けられるけど暗黙的にmoveになるっぽい
Avatar
ああ、letの他にmoveonlyが追加されてもuncopyableはついたままということですね
Avatar
Kishikawa Katsumi 3/1/2023 5:46 AM
https://github.com/apple/swift-package-manager/pull/6185 SwiftPMにもマクロのサポートが入った。.macroっていうターゲットタイプが新しくできるのね。
Add a new module CompilerPluginSupport which vends the macro target type Represent macro targets in the package model Build system support for macros In order to be able to test this end-to-end be...
5:48 AM
.executable, .snippet, .library(.dynamic), .macro こうしてみると .macroってプロダクトタイプは最終的に何になるんだって感じが気になるけど。
Avatar
マクロって普通のlibraryターゲットのソースコードの中についでで混ぜたりすることってできないんでしたっけ?
Avatar
Kishikawa Katsumi 3/1/2023 5:52 AM
そこは全然わかんないんですよね。私もそんなふうにライブラリの一部として配布するものだと考えてたんですけど、まさか.macroっていうのが追加されるとは思ってなかった。
Avatar
omochimetaru 3/1/2023 5:53 AM
普通のtargetをmacroに入れ込めるみたいなので、targetに本体をほぼ入れておけば、ライブラリに混ぜたりもできそう
Avatar
.macro ターケット(コンパイラプラグイン)はホストマシン向けにビルドされて、普通のライブラリ (macro  declaration を書くとこ) は ターゲットマシン向けにビルドされるものなので別ですね。 (edited)
Avatar
omochimetaru 3/1/2023 4:41 PM
おおたしかに
Avatar
普通のtargetをmacroに入れ込めるみたいなので、targetに本体をほぼ入れておけば、ライブラリに混ぜたりもできそう
できるかもだけど、その targetが SwiftSyntax を import するようになって、おそらく必要ないものなので無駄になっちゃう。
Avatar
SwiftPMのマクロサポートのピッチでました https://forums.swift.org/t/pitch-package-manager-support-for-custom-macros/63482
Introduction Macros provide a way to extend Swift by performing arbitary syntactic transformations on input source code to produce new code. One example for this are expression macros which were previously proposed in SE-0382. This proposal covers how custom macros are defined, built and distributed as part of a Swift package. Motivation SE-03...
Avatar
マクロの実装(ホスト向け)、マクロのシグネチャに出てくる型定義(クライアント向け)とでターゲットが分かれるんですね。なるほど。
Avatar
omochimetaru 3/2/2023 8:36 PM
サンプルだとMacroDefで定義するマクロシグネチャの右辺の#externalMacroのためにMacroImplへの依存関係がついてんのかな ここはダイナミックな名前参照するだけなのかと思ってたけど、たしかにMacroImplにバグがあったりしたら気づいてほしいし、ビルド依存関係があるといえばあるのか。
Avatar
マクロの実装が変わったら展開後のソースが変化するので、ビルド依存ありってことですかね。あとは単純に MacroDef が MacroImpl を使うっていうのが SwiftPM 的にわからんと macro ターゲットをビルドする理由がない。
Avatar
Avatar
rintaro
マクロの実装が変わったら展開後のソースが変化するので、ビルド依存ありってことですかね。あとは単純に MacroDef が MacroImpl を使うっていうのが SwiftPM 的にわからんと macro ターゲットをビルドする理由がない。
omochimetaru 3/3/2023 4:01 AM
わからんとビルドする理由がない
あーたしかにそうでした。 名前が書いてあるのは利用側も実装側もソースコード内部の情報だからビルドシステムとしては感知しないところだった。
Avatar
omochimetaru 3/9/2023 4:03 PM
Hi everyone. The review of SE-0392: Custom Actor Executors begins now and runs through March 21, 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 direc...
👀 1
4:03 PM
カスタムエグゼキュータ審査入り
Avatar
既存の見えてるインターフェースだいたいそのままって感じですね
4:53 PM
actorに個別のserialExecutor渡してinitされてるサンプルが紹介されてる、NIOのeventLoopの受け渡しがそのままactorになったという感じがしますね
Avatar
omochimetaru 3/9/2023 10:33 PM
ピッチともそんなに変わってないな
  • moveonly が入った前提になってる
  • Job.Priority = Task.PriorityJobPriority
  • runSynchronouslyのメソッドとレシーバが反転
Avatar
Avatar
Iceman
actorに個別のserialExecutor渡してinitされてるサンプルが紹介されてる、NIOのeventLoopの受け渡しがそのままactorになったという感じがしますね
omochimetaru 3/9/2023 10:36 PM
特定のEventLoopで自身の処理を実行するオブジェクトを実装するときに、EventLoopを受け取るactorにするってパターンで書く感じになるのかな?
10:37 PM
ただそれだとステートフルになるんだよな structで書く限りステートレスなのが良いんだけどな
Avatar
actorでもletなら別に良くないですか?
1:12 AM
あと、actorになるのはRequestだけで、Controller各種はそれをisolatedで受け取るパターンも考えられますね
Avatar
omochimetaru 3/10/2023 1:15 AM
うーん。classと同じでactor Aがプロパティのletで持ってるその先のactor Bがステートを持ってる場合とかもあるからなあ。 あ、isolatedは面白いかも。
Avatar
letで持ってる先のオブジェクトが状態を持つのはstructでも同じだと思います
Avatar
omochimetaru 3/10/2023 1:18 AM
それはそう。Aは変わらないですね Bをstructで書けるとそこが嬉しいという意味
1:19 AM
isolatedはまさにこの目的で使える機能な気がします
1:19 AM
自身をactorにしないままactor保護できるから。
Avatar
https://twitter.com/giginet/status/1634059356181495809?s=20 これ皆さんどうしてるんですかね
単なるstatic letのNotification.Nameがmain actor isolatedなのおかしいだろ、と思って調べてたら同じこと困ってる人がいたけど、Apple様の公式回答は「全部メインスレッドから使ってくれ」とか言っていて厳しい https://t.co/5YK7SN1wsA
7:41 AM
お試しでstrict-concurrencyを引き上げて遊んでるけど、どうしようもない場面にいくつか遭遇する
7:41 AM
iOS SDKがSwiftの進化に追いついていない
Avatar
発火する側は困りそうだけど購読する側はMainActorでもいいがちだから困ってなかった
Avatar
omochimetaru 3/10/2023 7:44 AM
Notification.Nameって文字列から自力でinitできないんだっけ?
7:44 AM
自前で別名で再定義してしまえば回避できそう・・・
Avatar
Kishikawa Katsumi 3/10/2023 7:52 AM
任意の文字列でできるよ。今のところ面倒だけど必要な分をそうするしかないんじゃないかな。
Avatar
やはりそうするしかないですよね。もしくはactor isolatedなところに固定値を退避させるとか
Avatar
Kishikawa Katsumi 3/10/2023 8:21 AM
どうせ受け手がMain threadにディスパッチするのであれば送る側がMain threadにディスパッチしても一緒だしそれでもいい気はする。
8:22 AM
UIKitとAppKitに関係ないNotification.Nameは別になんもついてないんですよね、きっと。
Avatar
受け取り側がメインスレッドで受け取るなら送信側も必ずメインスレッドで送るべきな気がする。別にNotificationCenterはスレッド切り替えの機構は持ってないと思います。
8:34 AM
複数スレッドで動くのはあくまで「任意のスレッドで送信し、送信されたスレッドで受け取ることが出来る」であって
8:34 AM
「任意のスレッドで送信し、任意のスレッドで受け取ることが出来る」ではない、と理解しています
Avatar
Kishikawa Katsumi 3/10/2023 8:35 AM
そうそう。
任意のスレッドで送信し、送信されたスレッドで受け取ることが出来る
NotificationCenterは基本postしたスレッドで受け手のスレッドが呼ばれるという動作をするはず。
(edited)
Avatar
そういう意味で、Notification.Nameがactor越境出来なくなってるのは、至極正しい実装に思えます。UIKit,AppKit関連ならMainActorであることは妥当に思える
Avatar
Kishikawa Katsumi 3/10/2023 8:38 AM
つまり送信側が必ずメインスレッドから送るべき、ってことね。 (edited)
👉 1
8:39 AM
今までアップルの実装も明確じゃないから安全のために結局受ける側がメインスレッドにディスパッチしてたけどそれをしなくてよくなる、はず。
Avatar
observeにOperationQueue渡して、クロージャの動作するqueueを指定する機能あったと思うんですが
8:41 AM
これはNotificationCenterがネイティブ対応してると言うよりは、シンプルなラッパーなのではないかと思います。ちょっとうろ覚えだが、コールスタックはそんな感じになってたと思う
Avatar
Kishikawa Katsumi 3/10/2023 8:42 AM
わしも詳しく調べたわけじゃないけどそうだと思う。自分でディスパッチしなくていいってだけで、クロージャの呼び出しをラップする、たぶん実装はクロージャをキューに突っ込んでるんだと思う。
Avatar
これOperationQueueを渡せる機能が存在したことで、大きな誤解が広まったのでは、という感じがしてきました
Avatar
なるほどー確かに
Avatar
omochimetaru 3/10/2023 8:45 AM
あ〜なるほど。UIKit関連のイベントはそもそも送り側も受け側もメインスレッドでやるもんか。
Avatar
RxやCombineでラップする運用が長いのでそういう気持ち忘れてました (edited)
Avatar
Kishikawa Katsumi 3/13/2023 8:36 AM
Swiftマクロ、パッケージマネージャで配布して動かせるようになったわ。 https://github.com/kishikawakatsumi/swift-power-assert-macro マクロを提供する側の定義はこんな感じで、 // swift-tools-version: 999.0 import CompilerPluginSupport import PackageDescription let package = Package( name: "SwiftPowerAssert", platforms: [ .iOS("13.0"), .macOS("10.15") ], products: [ .library( name: "SwiftPowerAssertLib", targets: ["SwiftPowerAssertLib"] ), ], dependencies: [ .package( url: "https://github.com/apple/swift-syntax.git", branch: "main" ), ], targets: [ .macro(name: "SwiftPowerAssertPlugin", dependencies: [ .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), .product(name: "SwiftOperators", package: "swift-syntax"), .product(name: "SwiftParser", package: "swift-syntax"), .product(name: "SwiftParserDiagnostics", package: "swift-syntax"), .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), ] ), .target(name: "SwiftPowerAssertLib", dependencies: ["SwiftPowerAssertPlugin"] ), ] ) マクロを使う側の定義はこう。ライブラリを依存関係に追加するだけで使う側はそれがマクロを含んでるかどうかはPackage.swiftを見るだけだとわからない。普通にライブラリを導入するのと一緒。だと思う。 // swift-tools-version: 999.0 import PackageDescription let package = Package( name: "swift-power-assert-client", platforms: [ .iOS("13.0"), .macOS("10.15") ], products: [ .executable( name: "swift-power-assert-client", targets: ["swift-power-assert-client"] ), ], dependencies: [ .package( url: "https://github.com/kishikawakatsumi/swift-power-assert-macro.git", branch: "main" ), ], targets: [ .executableTarget( name: "swift-power-assert-client", dependencies: [ .product(name: "SwiftPowerAssertLib", package: "swift-power-assert-macro") ] ), ] ) (edited)
👍 4
👀 1
Avatar
よさそう
Avatar
Kishikawa Katsumi 3/13/2023 8:58 AM
マクロを別に提供したいっていうのもパッケージングのやり方でどうにでもできそうだ。
Avatar
@noncopyable、いつの間にか ~Copyable になってますね
2:54 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0390-noncopyable-structs-and-enums.md at main · apple/swift-evolution
2:58 AM
~Sendable~Equatable の例も書かれてるし、~P の文法が新たに追加されるのかな?
2:58 AM
地味に嬉しいかも
Avatar
~なのかあ。!もいいかも。
Avatar
NonCopyable プロトコルみたいな否定への準拠だとだめな例が面白い extension Dictionary: NonCopyable where Key: NonCopyable, Value: NonCopyable https://forums.swift.org/t/pitch-noncopyable-or-move-only-structs-and-enums/61903/28
Avatar
Kishikawa Katsumi 3/16/2023 3:14 AM
~ってそういう意味か。なんか〇〇Copyableみたいに思ってしまった。
t_wakaru 1
Avatar
omochimetaru 3/16/2023 5:57 AM
not Copyable が読みやすくないかねえ
Avatar
omochimetaru 3/16/2023 9:07 AM
暗黙のconsumingとしてプロパティにセットする時と、initの引数が書いてあるな
9:08 AM
普通のfuncの引数は逆に暗黙のborrowingなんだろうな
9:09 AM
これ内部的な+1/+0ルールと一緒ですね多分
9:11 AM
クラスを渡すときにretainがされないケースとされるケースと対応してる
Avatar
omochimetaru 3/16/2023 9:23 AM
クラスのストアドプロパティにコピー不能型がある場合そのアクセスはborrowingにできるけど
9:24 AM
同じことをコンピューテッドプロパティからはできなくて、getがowned semanticsだからreturnするところでconsumeしようとするがクラス本体が生き続けるのでダメ (edited)
9:25 AM
将来的にはreadアクセサを使ってborrowingで返せる
9:26 AM
今までどっちのプロパティでもあまり差が無かったけどこういうところに敏感なんだな
Avatar
omochimetaru 3/17/2023 9:30 AM
Observation Proposal: SE-NNNN Authors: Philippe Hausler, Nate Cook Review Manager: TBD Status: Awaiting implementation Changes Pitch 1: Initial pitch Pitch 2: Previously Observation registered observers directly to Observable, the new approach registers observers to an Observable via a ObservationTransactionModel. These models control th...
9:31 AM
Observationも更新されました computed propertyも購読できるようにするために、
9:31 AM
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] } } }
👍🏻 1
9:32 AM
ユーザーがcomputed propertyが依存するプロパティを定義できるようです これならたしかに動きそう
Avatar
ユーザ定義ならいけそうだ
Avatar
computed property の中の実装が変わったとき dependencies の方を変え忘れちゃいそうですね
Avatar
AsyncStream がすごいバッファリングして continuation.finish 呼ぶまで for await を呼ばないんだけどなぜだろう。 (edited)
7:38 AM
そもそもblock callだとダメなのか...
Avatar
みたいですね
Avatar
あいや、そこじゃないのか。
Avatar
そうかなと思ったけどbuildが完了しないとだめでblockコールするとダメだった
Avatar
jobのスイッチが発生してないのかも
7:41 AM
もしconsumerが同じスレッドにスケジュールされていればTask.yield()で制御を明け渡さないとだめかも
😲 1
Avatar
Task.detachedしたら動いたのでそういうことっぽいです
7:41 AM
APIデザインむずいw
Avatar
これムズいですよねぇ
Avatar
Task.detached したら Consider using asynchronous alternative function 怒られた...
😇 1
7:45 AM
これObjective-C++側で worker thread つくって Objective-C++ API をconcurrent にしたほうがいいのかも...
Avatar
Consider using asynchronous alternative functioncompletionHandler じゃなくて、asyncメソッドとして呼んだら消えないですかね let error = await self.chat.predictTokens(for: prompt, tokenHandler: { token in continuation.yield(token) }) continuation.finish(throwing: error) (edited)
Avatar
おー
7:59 AM
消えた
✌️ 1
7:59 AM
do { try await self.chat.predictTokens(for: prompt) { token in continuation.yield(token) } continuation.finish() } catch { continuation.finish(throwing: error) } (edited)
7:59 AM
do - catch がださい
Avatar
throwsも付くんだw
Avatar
func predictTokens(for prompt: String, tokenHandler: ((String) -> Void)?) async throws
8:00 AM
ですね....
8:01 AM
まあでもObjective-CのAPI使う人から考えればそっちがconcurrentになってないのはきもいかな。 (edited)
Avatar
Task.detachedも無限にプール持ってるわけではないので、専用スレッドを自前で管理する必要があると思いますよ
8:09 AM
他のTask.detachedされた処理が詰まると思います
Avatar
なるほど
Avatar
cancelに対応させるためにはどっちにしろC++側で何かする必要がある...
Avatar
VariadicGenerics来ましたね func zip<each S>(_ sequence: repeat each S) where each S: Sequence struct Pair<First, Second> { init(_ first: First, _ second: Second) } func makePairs<each First, each Second>( firsts first: repeat each First, seconds second: repeat each Second ) -> (repeat Pair<each First, each Second>) { return (repeat Pair(each first, each second)) } let pairs = makePairs(firsts: 1, "hello", seconds: true, 1.0) // 'pairs' is '(Pair(1, true), Pair("hello", 2.0))' https://forums.swift.org/t/se-0393-value-and-type-parameter-packs/63859 (edited)
Hello Swift community, The review of SE-0393: Value and Type Parameter Packs begins now and runs through April 3, 2023. For those who've followed along during the pitch phase for this feature, you'll note that the proposed syntax has changed based on implementation experience. While it is within the scope of review to consider an alternative ...
👀 7
Avatar
omochimetaru 3/22/2023 4:55 AM
func < <each Element: Comparable>(lhs: (repeat each Element), rhs: (repeat each Element)) -> Bool
4:55 AM
読み始めたところだけど、結構変わったな
4:56 AM
トリプルドットじゃなくてeachキーワードだし、展開側にrepeatキーワードが付いてる
4:56 AM
初見に優しくなってそう
Avatar
omochimetaru 3/22/2023 7:44 AM
まあまあ形式的に書かれてるけど話がややこしくて英語が難しい・・・
t_desune 1
7:47 AM
初期の案だと曖昧になるケースがあったんだけど、今回は型の型パラメータでの利用は無しの仕様で、関数の型パラメータだけだから、その手の問題は回避してるのか・・・?
Avatar
repeat each is not a single production in the grammar; they don't always appear as consecutive tokens. repeat (each T, Int) means something other than (repeat each T, Int). If we substitute T for String, Bool, the first one becomes (String, Int), (Bool, Int) while the second is (String, Bool, Int).
11:56 PM
T = {String, Bool} のとき repeat (each T, Int) => (String, Int), (Bool, Int) (repeat each T, Int) => (String, Bool, Int)
👀 1
11:56 PM
このようにrepeatがどこにかかってるかで意味が変わる (edited)
11:57 PM
ユーザーとしてはこの部分の理解がミソっぽい (edited)
11:59 PM
書き込みでは each Teach 要らなくない?って意見が結構多い 実際意味解析としては T がパック型なのはわかってるから無くても良い文法にはできるけど チームとしてはマーキングされていることで読みやすい事が重要って意見っぽい (edited)
t_naruhodo 1
Avatar
Kishikawa Katsumi 4/5/2023 6:22 AM
Swiftのマクロを使ってPower Assertのライブラリを作りました。 https://github.com/kishikawakatsumi/swift-power-assert Power Assertは #powerAssert(xs.contains(4)) | | | | false 4 [1, 2, 3] ^ こんな感じで1つのAssert関数だけでリッチなAssertの情報を出力してくれるというものです。 将来の新機能であるマクロを使っているのでDevelopment Snapshotのツールチェーン( https://www.swift.org/download/ ) をインストールする必要がありますが、それだけで実際のプロジェクトにテストフレームワークとして組み込んで使えます。 Swiftマクロは現在は型情報を扱えないので、コードパターンをヒューリスティックに解析していろいろなパターンに対応しています。 ただ、Assert関数にはほぼどんなコードでも渡せるので対応できてないパターンがまだまだあります。 もしよかったらこのライブラリを使ってみていろいろなパターンを試してください。コンパイルエラーが起こったり、正しく動いてなさそうな例があったら教えてください。
Power Assert in Swift. Contribute to kishikawakatsumi/swift-power-assert development by creating an account on GitHub.
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
👀 1
👏🏻 6
Avatar
@Kishikawa Katsumi PowerAssert って現状ざっくり PowerAssert.Assertion("foo.bar(baz)") .assert(foo.bar.baz()) .capture(expression: foo.bar(baz), column: 4) .capture(expression: foo, column: 0) .captuer(expression: baz, column: 8) みたいに展開するとおもうんですが、下みたいにしたら、副作用ある式でも対応できて評価が一回で済むかなと思ったのですが、 PowerAssert.Assertion("foo.bar(baz)") { (values: inout [Value]) throws -> Bool in func _capture<T>(_ expr: @autoclosure () throws -> T, column: Int) rethrows -> T { let val = try expr() values.append(Value(value: _toString(val), column: column)) return val } return try _capture(_capture(foo, column: 0).bar(_capture(baz, column: 8)), column: 4) } なにか落とし穴あります? (edited)
Avatar
omochimetaru 4/6/2023 1:16 AM
なるほど。 foo.bar(baz) の評価木の各ノードに capture を差し込んだ形だ
Avatar
Avatar
omochimetaru
なるほど。 foo.bar(baz) の評価木の各ノードに capture を差し込んだ形だ
言語化感謝🙂
😀 1
Avatar
Kishikawa Katsumi 4/6/2023 1:33 AM
意図としては下の行を増やさないようにという設計があります。
1:34 AM
ただマクロで下の行の行番号が変わらないなら問題ないすね。テストの結果の出力で行番号が変わるとわからなくなるかなという昔の設計を引きずってるやつです。
1:34 AM
tryが簡単になるのはとてもいいですね。tryの扱いは難産だったので。
Avatar
あーなるほど、#line を維持したかったということですね
1:36 AM
tryは試してないのでそれで行けるかどうか確信ないです
Avatar
Kishikawa Katsumi 4/6/2023 1:37 AM
了解です。試してみます。めっちゃ感謝です🥰
Avatar
try の苦労って throws かどうかを知らずに try を書きたいってことだと思うので、無条件 throws な関数適当に作っておけば func _throwsShim<T>(_ value: T) throws -> T { value } func test() throws -> Int { return try _throwsShim(1) } とかで良さそう、そしたら _capture は @autoclosurerethrows もいらず, (edited)
2:03 AM
func _capture<T>(_ value: T, column: Int) -> T { values.append(Value(value: _toString(value), column: column)) return value } return try _throwsShim(_capture(_capture(foo, column: 0).bar(_capture(baz, column: 8)), column: 4)) とか。
Avatar
Kishikawa Katsumi 4/6/2023 2:09 AM
おお、ダミーのthrows関数を挟むと警告なしにtryが書けるんですね。
2:11 AM
そうすると全部にtryが書けて try! JSONEncoder().encode(landmark) == #"{"name":"Tokyo Tower"}"#.data(using: String.Encoding.utf8) ^ のパターンで右辺を独立に評価したときにtryがないとコンパイルエラーっていうのが簡単に扱えそうです。 (edited)
Avatar
omochimetaru 4/6/2023 2:37 AM
あ~なるほど tryが根本にかかってるときに、部分式がthrowsかどうかがわからないから難しかったのか。
Avatar
Kishikawa Katsumi 4/6/2023 2:58 AM
そうなんす。今は左側のノードにtryがあったらtryを書くことで妥協しています。 余分なtryを書くぶんにはエラーにはなりませんが、全部にやると警告だらけになるので、というバランスです。
Avatar
omochimetaru 4/8/2023 3:09 AM
co-author: Holly Borla Introduction Building upon the Value and Type Parameter Packs proposal SE-0393, this proposal enables referencing a tuple value that contains a value pack inside a pack repetition pattern. Motivation When a tuple value contains a value pack, there is no way to reference those pack elements or pass them as a value pack ...
Avatar
omochimetaru 4/8/2023 3:19 AM
元の話と同じに見える・・・
3:20 AM
func example<each U>(packElements value: repeat each U, tuple: (repeat each U)) { print((repeat each value)) print((repeat each tuple)) print((repeat (each value, tuple))) print((repeat (each value, each tuple))) } example(packElements: 1, 2, 3, tuple: (4, 5, 6)) // Prints the following output: // (1, 2, 3) // (4, 5, 6) // ((1, (4, 5, 6)), (2, (4, 5, 6)), (3, (4, 5, 6))) // ((1, 4), (2, 5), (3, 6))
3:21 AM
これ4通り読み取れてればユーザとしては良さそう
Avatar
Kishikawa Katsumi 4/8/2023 2:36 PM
@swift-5.8.1 func f<T>(_ expr: T) -> T { let val = expr return val } let i = 0 _ = f([0]).firstIndex(of: 0) == i _ = f([0]).firstIndex(of: 0) != i
Avatar
Avatar
Kishikawa Katsumi
@swift-5.8.1 func f<T>(_ expr: T) -> T { let val = expr return val } let i = 0 _ = f([0]).firstIndex(of: 0) == i _ = f([0]).firstIndex(of: 0) != i
swift58 BOT 4/8/2023 2:36 PM
exit status: 1 with <stdin>:8:12: error: value of optional type 'Int?' must be unwrapped to a value of type 'Int' _ = f([0]).firstIndex(of: 0) != i ^ <stdin>:8:12: note: coalesce using '??' to provide a default when the optional value contains 'nil' _ = f([0]).firstIndex(of: 0) != i ^ ?? <#default value#> <stdin>:8:12: note: force-unwrap using '!' to abort execution if the optional value contains 'nil' _ = f([0]).firstIndex(of: 0) != i ^ !
Avatar
Kishikawa Katsumi 4/8/2023 2:37 PM
@swift-4.2.4 func f<T>(_ expr: T) -> T { let val = expr return val } let i = 0 _ = f([0]).firstIndex(of: 0) == i _ = f([0]).firstIndex(of: 0) != i
2:39 PM
^ Swift 5から f([0]).firstIndex(of: 0) == i は合法だけど、 f([0]).firstIndex(of: 0) != i は(==!=の違い)コンパイルエラーになるのだけどどうしてだろう?
Avatar
Kishikawa Katsumi 4/8/2023 2:46 PM
Swift 4ではどっちもコンパイル可能なことは独自に確認しました。
Avatar
@swift-5.8.1 func f<T>(_ expr: T) -> T { let val = expr return val } let i = 0 _ = f([0]).firstIndex(of: 0) == i _ = f([0] as [Int]).firstIndex(of: 0) != i (edited)
Avatar
Avatar
kebo
@swift-5.8.1 func f<T>(_ expr: T) -> T { let val = expr return val } let i = 0 _ = f([0]).firstIndex(of: 0) == i _ = f([0] as [Int]).firstIndex(of: 0) != i (edited)
swift58 BOT 4/8/2023 3:04 PM
no output (edited)
Avatar
こう型アノテーションすると通るんで [0] の型推論の問題なんですかね (T.Index の) (edited)
Avatar
Kishikawa Katsumi 4/8/2023 3:05 PM
そんな感じっぽい挙動ですよね。i をリテラルにしても通りました。
Avatar
Kishikawa Katsumi 4/8/2023 10:53 PM
func f<T>(_ expr: T) -> T { let val = expr return val } func f<T>(_ expr: [T]) -> [T] { let val = expr return val } let i = 0 _ = f([0]).firstIndex(of: 0) == i _ = f([0]).firstIndex(of: 0) != i func f<T>(_ expr: [T]) -> [T] のオーバーロードを用意してやるのでもいけた。呼び出す側のコードを変更 しない解決方法ならこれがよさそう。
😮 1
Avatar
Array 以外でも再現するので (Stringと Int 確認しました)、リテラル系はとりあえずオーバーロード用意しておいたほうが良さそうですね。 とはいえ ユーザ定義の *LiteralExpressible だと失敗しそう。 TypeChecker の人がバグと判断するかはわかりませんが、issueたてていただけるとありがたいです。 @swift-5.8.1 func id<T>(_ val: T) -> T { val } func test(c: Character) { id("").first != c } (edited)
Avatar
Avatar
rintaro
Array 以外でも再現するので (Stringと Int 確認しました)、リテラル系はとりあえずオーバーロード用意しておいたほうが良さそうですね。 とはいえ ユーザ定義の *LiteralExpressible だと失敗しそう。 TypeChecker の人がバグと判断するかはわかりませんが、issueたてていただけるとありがたいです。 @swift-5.8.1 func id<T>(_ val: T) -> T { val } func test(c: Character) { id("").first != c } (edited)
swift58 BOT 4/9/2023 2:30 AM
exit status: 1 with <stdin>:4:10: error: value of optional type 'String.Element?' (aka 'Optional<Character>') must be unwrapped to a value of type 'String.Element' (aka 'Character') id("").first != c ^ <stdin>:4:10: note: coalesce using '??' to provide a default when the optional value contains 'nil' id("").first != c ^ ?? <#default value#> <stdin>:4:10: note: force-unwrap using '!' to abort execution if the optional value contains 'nil' id("").first != c ^ !
Avatar
個人的には適用できる Solution があるのに見つけられてないのでバグと主張していいと思います。
Avatar
Kishikawa Katsumi 4/9/2023 2:36 AM
どうもどうも。ありがとうございます。Issueを作ります。
Array 以外でも再現するので (Stringと Int 確認しました)、リテラル系はとりあえずオーバーロード用意しておいたほうが良さそうですね。
なるほどこれは気づいてなかったです。 あとOptionalも同様にオーバーロード必要でした。
(edited)
Avatar
Avatar
rintaro
@Kishikawa Katsumi PowerAssert って現状ざっくり PowerAssert.Assertion("foo.bar(baz)") .assert(foo.bar.baz()) .capture(expression: foo.bar(baz), column: 4) .capture(expression: foo, column: 0) .captuer(expression: baz, column: 8) みたいに展開するとおもうんですが、下みたいにしたら、副作用ある式でも対応できて評価が一回で済むかなと思ったのですが、 PowerAssert.Assertion("foo.bar(baz)") { (values: inout [Value]) throws -> Bool in func _capture<T>(_ expr: @autoclosure () throws -> T, column: Int) rethrows -> T { let val = try expr() values.append(Value(value: _toString(val), column: column)) return val } return try _capture(_capture(foo, column: 0).bar(_capture(baz, column: 8)), column: 4) } なにか落とし穴あります? (edited)
Kishikawa Katsumi 4/10/2023 1:32 AM
https://github.com/kishikawakatsumi/swift-power-assert/pull/9 やってみました。いくつか元の処理だとできてた部分がうまく動かない部分がまだあるのですが逆に今まで無理してた部分が自然になったところも多いのと、コード生成の処理がかなりシンプルになったのでこちらの方が良さそうです。現状うまくいかなくない部分も調整すればたぶん解決できそう。 Positive: コード生成の処理が簡単になった。 Positive: 評価が一回になったので副作用のある式でもダンプした値と実際の値が一致するようになった。 Positive: "...".data(using: .utf8)).utf8のような独立して評価すると型情報が足りないような式も全体で評価できるから型推論が効いてしてコンパイルできるようになった。 capture("...").data(using: capture(.utf8))みたいなコード生成になってコンパイルできる。 Positive: SyntaxRewriterを使って〜〜ExprSyntaxを対象にする、としたので今までのコードパターンから考えるやり方よりシステマチックにできるようになった。 Neutral: 動作したときに評価されなかった値はそもそも実行されないので出力されない。 (例)三項演算子の片方、|| で短絡評価された場合の残りの式など。 (edited)
Changed to a code generation that does not affect the evaluation of expressions containing side effects. Before: PowerAssert.Assertion("foo.bar(baz)") .assert(foo.bar.baz()) .capture(...
Avatar
Kishikawa Katsumi 4/10/2023 1:44 AM
一番困っているのは c?.property.performAction() っていうOptional Chainを含む式は次のようなコードが生成されるんですけど、 PowerAssert.Assertion("", file: "", line: 0) { $0.capture( $0.capture($0.capture($0.capture(c.self, column: 13)?, column: 13).property, column: 16) .performAction(), column: 25) } この場合、 $0.capture(c.self, column: 13)?, column: 13).property, column: 16).performAction(), column: 25).performAction()?.performAction()としないとコンパイルエラーになるんですよね。そのもともと付いてなかった?をどう付けたらいいものかっていうところが困っています。
Avatar
omochimetaru 4/10/2023 2:03 AM
c?. ←ここから c がオプショナルであることがわかるから・・・ func captureOptional<T>(_ value: T?, column: Int, next: (T) -> Void) { ... } ↑こういうユーティリティを追加して captureの代わりにcaptureOptionalを適用するようにして PowerAssert.Assertion(...){ (PA) in PA.captureOptional(c, column: 1) { (c) in PA.capture(c.property, column: 3).performAction(), column: 25) } } こんな感じにして、 cnil のときは .property.performAction も評価されない (||と同じ) とする・・・?
2:03 AM
生成されたコードがややこしいので、 capture も継続渡しに修正して
2:04 AM
PowerAssert.Assertion(...){ (PA) in PA.captureOptional(c, column: 1) { (c) in PA.capture(c.property, column: 3) { (property) in PA.capture(property.performAction(), column: 25) } } } ↑こうしたほうが、元の式を左から右に書き下せて良いかもしれませんね。
2:05 AM
このアプローチだと、もし元の式が c?.property?.performAction() と、 ?. が更に入っていた場合も PowerAssert.Assertion(...){ (PA) in PA.captureOptional(c, column: 1) { (c) in PA.captureOptional(c.property, column: 3) { (property) in PA.capture(property.performAction(), column: 25) } } } ↑このようにうまく対応付けられるはず (edited)
Avatar
Kishikawa Katsumi 4/10/2023 2:16 AM
ありがとう、やってみる。
Avatar
この用途なら手書きの継続渡しじゃなくて例外でも良さそう
Avatar
omochimetaru 4/10/2023 2:18 AM
たしかに!
2:18 AM
throw NilCaptureError() して、 PoserAssert.Assertioncatch してしまうのね。 (edited)
Avatar
そうそう
Avatar
omochimetaru 4/10/2023 2:18 AM
そのほうが現在の実装から大きく変更せずに対応できそう。
Avatar
うまい、なるほど
2:20 AM
?.で短絡される処理とtryで抜け出す範囲が一致しててうまくいく
Avatar
Avatar
Kishikawa Katsumi
ありがとう、やってみる。
omochimetaru 4/10/2023 2:21 AM
もうやってみちゃってるかもしれませんがnilだったら例外投げる方式も検討したほうが良いかも (edited)
Avatar
Kishikawa Katsumi 4/10/2023 2:21 AM
まだ取りかかってないから大丈夫☺
Avatar
なるほどーいろいろな罠と効果があっておもしろいですね。
Neutral: 動作したときに評価されなかった値はそもそも実行されないので出力されない。
これはちょっと思ってたんですが、評価対象のexpr位置はわかっているので $0.capturing(columns: [13,16,25]) とか予約しておいて、capture() 呼ばれなかったところは評価されなかったことがわかるようにすると、不具合っぽくないし、テスト結果としても有用かなと思いました。
(edited)
Avatar
Kishikawa Katsumi 4/10/2023 3:28 AM
あーそれは良さそう。やってみます。作ってて実装もれなのかかなりわかりにくかったんですよね。自分でもなんでここでないんだろうって何度もハマった。
3:31 AM
あとは error: the compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions これが新しく出るようになったパターンがあるのですが、調べようと思って普通のプロジェクトにCopy&Pasteすると特に問題なくコンパイルできたりしてまだ詳細がわかってないのでわかったらまた相談に乗ってください。 (ツールチェーンの違いとかでもなかった。あとはXCTestの環境かどうかとXcodeとSwiftのコマンドラインとの違い、くらいかなあ。)
Avatar
むむー type checker が弱音を吐くパターンは出てきそうですねー
Avatar
Avatar
Yuta Saito
この用途なら手書きの継続渡しじゃなくて例外でも良さそう
foo?.bar() == expected みたいなときに throw しちゃうと途中で終わっちゃうかも。
😯 1
Avatar
omochimetaru 4/10/2023 3:38 AM
foo?.bar() の範囲で do-catch しなきゃいけないのか。
3:39 AM
でもそれには文を分けないといけない・・・
Avatar
Kishikawa Katsumi 4/10/2023 3:39 AM
簡単な例だと下記のコードは let initializer: (Int) -> String = String.init #expect([1, 2, 3].map(initializer).reduce("", +) == "123", verbose: true) こういうコードを生成して PowerAssert.Assertion( #"#powerAssert([1, 2, 3].map(initializer).reduce("", +) == "123")"#, message: "", file: #""PowerAssertTests/PowerAssertTests.swift""#, line: 1712, verbose: true ) { $0.capture( $0.capture( $0.capture( $0.capture( [$0.capture(1, column: 14), $0.capture(2, column: 17), $0.capture(3, column: 20)], column: 13 ).map($0.capture(initializer.self, column: 27)), column: 23 ).reduce($0.capture("", column: 47), +), column: 40) == $0.capture("123", column: 57), column: 54) }.render() swift test で実行した場合はunable to type-checkなんですけど手元の別のXcodeプロジェクトにコピーした場合は問題なかったり。よくわからない。
Avatar
PowerAssert.Assertion("", file: "", line: 0) { $0.capture( $0.capture($0.capture($0.capture(c.self, column: 13)?, column: 13).property, column: 16) .performAction(), column: 25) } これって $0.capture($0.capture($0.capture(c.self, column: 13)?, column: 13). がコンパイル通らないので
3:40 AM
optional チェーンはcapture 挟まないようにして $0.capture( $0.capture($0.capture($0.capture(c.self, column: 13), column: 13).property, column: 16)? .performAction(), column: 25) ではだめですか? (edited)
Avatar
omochimetaru 4/10/2023 3:41 AM
func optionalCatch<R>(body: () throws -> R) { ... } こうしておいて capture( optionalCatch { try capture(captureOptional(foo).bar) } ) == capture( expected ) こうか (edited)
Avatar
Avatar
rintaro
PowerAssert.Assertion("", file: "", line: 0) { $0.capture( $0.capture($0.capture($0.capture(c.self, column: 13)?, column: 13).property, column: 16) .performAction(), column: 25) } これって $0.capture($0.capture($0.capture(c.self, column: 13)?, column: 13). がコンパイル通らないので
Kishikawa Katsumi 4/10/2023 3:48 AM
あ、これ整形のときのミスですね。ごめんなさい。 $0.capture($0.capture(c.self, column: 13)?.property, column: 16).performAction() 生成されたコードはこうでした。
Avatar
あーなるほど。
Avatar
Kishikawa Katsumi 4/10/2023 3:49 AM
で、 $0.capture($0.capture(c.self, column: 13)?.property, column: 16)?.performAction() と?.performAction()にハテナが必要。
Avatar
omochimetaru 4/10/2023 3:50 AM
その performAction にハテナが必要なことは c?.property のハテナからわかりません? (edited)
Avatar
なんか syntactic に?つける手もある気がする (edited)
3:50 AM
子に optional chain があったら親に伝播させていけばよいから。
Avatar
omochimetaru 4/10/2023 3:50 AM
a.b.c?.d.e.f みたいなとき、分解して考えると ?.d?.e?.f が必要
Avatar
Kishikawa Katsumi 4/10/2023 3:51 AM
こういうSyntax Treeがくる。
3:52 AM
ハテナを追加でつけるならOptionalChainingExprをvisitしたときに上のノードを辿るかFunctionCallExprをvisitしたときに子を検査する、かなあ。
Avatar
visit の帰りでラップしていけば 親に状態伝播しながらどうラップするか決められませんか?
Avatar
Kishikawa Katsumi 4/10/2023 3:56 AM
やってみます。
Avatar
Kishikawa Katsumi 4/10/2023 4:04 AM
Swiftマクロ改めて思ったのは仕様は問題ないと思うけどSwiftSyntaxがやっぱり難しい。そこがいちばん問題になると思う。ここ1、2年でだいぶ変わっててChatGPTさんもあまり助けてくれないし。
🙇‍♂️ 1
4:05 AM
マクロがリリースされたらノウハウの共有も進むかもしれない。
Avatar
Kishikawa Katsumi 4/10/2023 8:39 AM
ハテナを付けるっていうやり方でとりあえずうまくいった気がします。みなさんどうもありがとう🥰 https://github.com/kishikawakatsumi/swift-power-assert/pull/11
Fixed a problem where code generation would fail for expressions containing an optional chain, like the following: var c: SomeClass? #expect(c?.property.performAction() == nil, verbose: true) c = ...
👏🏻 1
8:41 AM
そういえば細かい部分で結果が変わったことでいうと let zero = 0 let one = 1 let two = 2 let three = 3 let array = [one, two, three] #expect(array.firstIndex(of: zero) != two, verbose: true)
8:42 AM
のようにOptionalとNon-optionalを比較すると #expect(array.firstIndex(of: zero) != two) | | | | | | nil 0 | Optional(2) [1, 2, 3] true のように両方Optionalになる(例だとtwoは実際にはOptionalではない。)というのは確かに実際には両方Optionalに推論されるんだなというのがわかっておもしろかった。
Avatar
Avatar
rintaro
Array 以外でも再現するので (Stringと Int 確認しました)、リテラル系はとりあえずオーバーロード用意しておいたほうが良さそうですね。 とはいえ ユーザ定義の *LiteralExpressible だと失敗しそう。 TypeChecker の人がバグと判断するかはわかりませんが、issueたてていただけるとありがたいです。 @swift-5.8.1 func id<T>(_ val: T) -> T { val } func test(c: Character) { id("").first != c } (edited)
Kishikawa Katsumi 4/11/2023 10:38 AM
https://github.com/apple/swift/issues/65061 報告しました。現象が奇妙だから説明がだいぶ難しかった。
Description When I pass a literal expression as an argument to a generic function and compare its return value to another literal with a binary operator, the == case is not a problem, but ! = cause...
Avatar
味わい深い。不思議なバグですね。
Avatar
Kishikawa Katsumi 4/11/2023 11:01 AM
さっぱりわからん。困ってる人もほとんどいないんじゃないか。ただ私はめっちゃ困っている。
11:01 AM
バージョンをいろいろ変えて試したりしたところ、どうも==!=では型推論の処理が違うところ通るみたいだな。
Avatar
Equatable の requirement が == だけなので、 != と違うのはたぶんそう。 (edited)
😲 1
Avatar
Kishikawa Katsumi 4/12/2023 12:58 AM
var output: TextOutputStream = "" print("", to: &output) ^ なんかこのコード、コンパイラがSegmentation Faultしないですか?ウチの環境のせいかもしれないからちょっと自信がない。
Avatar
Kishikawa Katsumi 4/12/2023 1:07 AM
var output: some TextOutputStream = "" print("", to: &output) someつけたら通ったからなんかその辺の問題か。
Avatar
main だと SILGen で assert に引っかかりますね Assertion failed: (def->getFunction() == &F && "def of root local archetype is in wrong function"), function addTo, file SILInstructions.cpp, line 118.
Avatar
Kishikawa Katsumi 4/12/2023 2:14 AM
確認どうもです。報告しておきます🫡
🙇‍♂️ 1
Avatar
Kishikawa Katsumi 4/18/2023 1:08 PM
https://forums.swift.org/t/macros-accessing-the-parent-context-of-a-syntax-node-passed-to-a-macro/64443/14 マクロの親のノードが取れる要件、絶対にあったほうがいいんだけど明確なユースケースっていうとパッと出てこないな。
To me, there are currently three major categories of information not accessible by macros: Lexical context Type information about sub-expressions Reflection of arbitrary types It looks like the proposed addition would be sufficient to solve the first case, at least for the macros I have experimented with. I don't have a preference as to wheth...
Avatar
関数に渡された値をログに出力したい時に使えるみたいな書き込みがありましたね。 func myMethod(_ text: String, num: Int, flag: Bool) { #debugLog("message") } // myMethod("text", num: 4, flag: true): message https://forums.swift.org/t/macros-accessing-the-parent-context-of-a-syntax-node-passed-to-a-macro/64443/3 (edited)
Here's a use case: I have a theoretically-working prototype* of a macro that prints the enclosing context for logging. For instance, if you had func myMethod(_ text: String, num: Int, flag: Bool) { #debugLog("message") } The macro would expand to printing myMethod("text", num: 4, flag: true): message to the console, or whatever the actua...
Avatar
Kishikawa Katsumi 4/19/2023 6:06 AM
これはいい例ですよね。パラメータの型や数で記述変えなくていい。
t_desune 1
Avatar
Kishikawa Katsumi 4/25/2023 8:24 PM
https://github.com/apple/swift/pull/65299/files マクロで #assert が使えなかったのはStatic Assertっていう別の機能とぶつかってたかららしい。
#assert should be usable as a macro name, but the experimental feature was getting in the way. Fixes rdar://107894668.
Avatar
そういえばコンパイル時計算/定数とコンパイル時assertion途中までやってましたね でも #assert のパーサーの対応はそれより昔からあったような気がする 初期から気持ちだけあって進んでなかったようなものかも
Avatar
Kishikawa Katsumi 4/26/2023 4:27 AM
なるほどねえ。どこかで特別扱いしてるんだろうとは思ってたけどマクロじゃない機能のところでぶつかってるとはわからなかった。
4:30 AM
でもStatic AssertがAcceptedになったらまたそっち優先になりそうだな。今のところ進んでなさそうだけど
Avatar
omochimetaru 4/26/2023 4:31 AM
その問題はありますよねw
4:32 AM
コンパイル時assertion導入するならコードとしては #assert(foo == 3) がやっぱ一番キレイだと思うし・・・
4:32 AM
C++だと static_assert だけど、 # に、コンパイル時パラメータってニュアンスがありますからね。
Avatar
いやー、今回のマクロで # はマクロ展開のものっていう感じになるので、#assert コンパイル時assertion に #assert 使うことは無いと思いますよ。もしあったとしてもこの Doug の patch によって #assert マクロが一般開放されたので、組み込みマクロによって source breaking にならないように配慮されるはず (edited)
Avatar
omochimetaru 4/26/2023 4:36 AM
#if とかがあるので、 # はコンパイル時評価のもので、マクロはその一部って関係じゃないですかね? (edited)
4:37 AM
他にあるかな・・・ #file とかは確かにマクロとして改められた。
4:37 AM
#selector これはマクロにできそうな気がするなw (edited)
4:38 AM
if #available もあった
Avatar
組み込みマクロによって source breaking にならないように配慮されるはず
たとえば #assert(...) はマクロとして parse されて、名前解決により、組み込み assertion か 一般マクロかに解決されるとか
4:41 AM
#if などの組み込み #... がいくつか残るのは確かですが、僕の予想として、今後追加されるものは 一般マクロで実現出来ないものはそれなりの特別な命名をされるんじゃないかと思っています。
4:41 AM
といっても #staticAssert() 程度だとおもいますけどw
Avatar
omochimetaru 4/26/2023 4:45 AM
なるほど。 attached macroもあるから、 #foo@foo がユーザーに荒らされまくるから、 公式の機能追加の命名はだいぶ慎重になりそうだなあ・・・
Avatar
Kishikawa Katsumi 4/26/2023 4:49 AM
それなら#assertにしようかな。ForumにDougが書いてくれたんでそれに返信する形で聞こうかと思ってた。
4:50 AM
まあ聞いておこう。
4:51 AM
そういえばマクロも名前空間ってあるんだっけ。 #PowerAssert.assert() って書いてモジュールで区別できるのかな。
Avatar
#PowerAssert まででマクロと認識されてしまい、.assert() はその結果に対する普通のメソッド呼び出しになります。
Avatar
Kishikawa Katsumi 4/26/2023 4:53 AM
そうなんだ。そうするとマクロの名前は結構取り合いか。。。
Avatar
omochimetaru 4/26/2023 4:53 AM
手元で #powerAssert を定義して、実装を転送する事はできる?ユーザーにはできないんだっけ?
Avatar
Kishikawa Katsumi 4/26/2023 4:53 AM
あ、マクロは確かにエイリアスは作りやすいっすね。
Avatar
omochimetaru 4/26/2023 4:54 AM
@freestanding(expression) public macro powerAssert( _ expression: @autoclosure () throws -> Bool, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line, verbose: Bool = false ) = #externalMacro(module: "PowerAssertPlugin", type: "PowerAssertMacro") (edited)
4:54 AM
↑これだけ書く。 (edited)
Avatar
Kishikawa Katsumi 4/26/2023 4:54 AM
@~~~はモジュール名で区別できましたよね。そっちと合ってるほうがいい気がする。
Avatar
omochimetaru 4/26/2023 4:55 AM
#externalMacro(module: から指定ですね
Avatar
Kishikawa Katsumi 4/26/2023 4:56 AM
#externalMacro をクライアント側で書いて、同じ名前で上書きできるならいいけど、
4:56 AM
違う名前にする必要があるなら #PowerAssert.assert() `のほうがいいんじゃないかな。
Avatar
#PowerAssert まででマクロと認識されてしまい、.assert() はその結果に対する普通のメソッド呼び出し
ごめんなさい動作未確認。いずれにしても #ModuleName.macroName できるべきだと思うので、確認してできなかったらIssue あげていただけると。
Avatar
Kishikawa Katsumi 4/26/2023 4:57 AM
了解です🫡
5:01 AM
4/6あたりのツールチェーンだと無理そうですね。#PowerAssertってマクロを探そうとする。
Avatar
@ もマクロはダメみたいですね。 (edited)
Avatar
omochimetaru 4/26/2023 5:08 AM
PropertyWrapperって@Module.Name できたのか・・・
Avatar
typealiasも効きますからね
Avatar
Kishikawa Katsumi 4/26/2023 5:11 AM
Property WrapperってTypealiasできるんですか。 (edited)
Avatar
omochimetaru 4/26/2023 5:12 AM
型パラメータを複数持ったproperty wrapper作って、一部のパラメータだけ固定した版をtypealiasで作るみたいな事ができる
5:13 AM
似てるけど微妙に動作が違う複数のwrapperを作りたい時、差分の部分をプロトコルと型に切り出したりできて便利 (edited)
Avatar
Kishikawa Katsumi 4/26/2023 5:28 AM
なるほど!ジェネリックなProperty Wrapperを用意しておいてTypealiasで使いやすく特化したやつを提供できるんすね。
🙆‍♂️ 1
5:32 AM
Attached Macroだと同じことができたらよさそうな気もする。これは気がするだけ。
5:35 AM
MyCodableみたいなマクロを提供するとすると名前はモジュール名.Codableにしたい、みたいなことがあるかな。
5:40 AM
あ、TypeAliasの話じゃなかった。
5:41 AM
TypeAliasはパッと思いつかんな。
Avatar
omochimetaru 4/26/2023 5:44 AM
抽象的なマクロを作って挙動の変更を注入するみたいな事ですよねえ
5:44 AM
#externalMacro(module: "PowerAssertPlugin", type: "PowerAssertMacro") ↑今だと根本が結局これだからなんもできなさそうですけど・・・
5:47 AM
例えば、 (意味があるかは別として) #nyasuffix("hello") -> "hello nya" #wansuffix("hello") -> "hello wan" ↑みたいなやつを macro nyasuffix(...) = #externalMacro(module: ..., type: "GenericSuffix", suffix: "nya") macro wansuffix(...) = #externalMacro(module: ..., type: "GenericSuffix", suffix: "wan") ↑みたいにexternalMacroの部分でパラメータを渡すみたいな
Avatar
マクロを書くマクロ…
Avatar
omochimetaru 4/26/2023 5:49 AM
マクロプラグインの実装側でマクロを使うのは普通にできそう。
5:50 AM
↑はただの値パラメータをマクロプラグインに渡す例だけど、 「マクロを渡して完成する高階マクロ」みたいなものは更に複雑な仕様が必要そう ユースケースしらんけどw
5:51 AM
attached macroとかの場合で @FooBar って書いたら @Foo @Bar の2つになるみたいなのもあるかな これは今も実装可能だな (edited)
Avatar
Kishikawa Katsumi 4/26/2023 6:15 AM
たしかにマクロをまとめるマクロはほしいケースがありそうだな。 要するに typealias Codable = Decodable & Encodable ができるようになるってことね。
Avatar
omochimetaru 4/26/2023 6:16 AM
ですね
6:17 AM
今だと @Codable マクロを作って実装として @Decodable@Encodable をつけて中身をそのまま出す ってやる感じですね
6:17 AM
合成の詳細がプラグインのマクロロジックとして埋め込まれるから
6:17 AM
まあできるけど見通しはだいぶ悪そう
Avatar
Kishikawa Katsumi 4/26/2023 6:22 AM
なるほどProperty WrappersやResult Buildersと見た目が似てるから同じことできたらいいように見えるけど実際は難しいな。
6:23 AM
同じように使えないなら見た目を似せないほうがいいというセオリーもあるけど。
Avatar
Kishikawa Katsumi 4/26/2023 5:18 PM
https://forums.swift.org/t/introducing-swift-power-assert/64197/9 Compile time assertが正式になったとしても違う構文になるとのこと。
If compile time assertions are accepted some day, they could use a different syntax. Doug
Avatar
omochimetaru 4/26/2023 9:10 PM
おお、、、
Avatar
その時はなんかシュッとした構文をおさえてほしいな
Avatar
A new version of Foundation launched today as an open source project, written in Swift. This project provides a single, cross-platform implementation and shows significant performance improvements. https://t.co/ItMd423gvz
Likes
307
11:36 PM
Swift Foundationきたで
11:42 PM
In benchmarks parsing test data, there are improvements in decode time from 200% to almost 500%.
11:42 PM
jsondecoder速いらしい これは嬉しい
t_majika 2
t_kami 5
Avatar
2023前半は品質アップとコミュニティからのAPI追加をやって、URLやFileManagerは2023後半らしい ながいなあー
Avatar
@available(macOS 10.10, iOS 8.0, watchOS 2.0, tvOS 9.0, *) public func components<T : StringProtocol>(separatedBy separator: T) -> [String] { #if FOUNDATION_FRAMEWORK if _foundation_essentials_feature_enabled() { if let contiguousSubstring = _asContiguousUTF8Substring(from: startIndex..<endIndex) { let options: String.CompareOptions if separator == "\n" { // 106365366: Some clients intend to separate strings whose line separator is "\r\n" with "\n". // Maintain compability with `.literal` so that "\n" can match that in "\r\n" on the unicode scalar level. options = [.literal] } else { options = [] } do { return try contiguousSubstring._components(separatedBy: Substring(separator), options: options) } catch { // Otherwise, inputs were unsupported - fallthrough to NSString implementation for compatibility } } } return _ns.components(separatedBy: separator._ephemeralString) #else do { return try Substring(self)._components(separatedBy: Substring(separator), options: []) } catch { return [String(self)] } #endif }
12:07 AM
旧Foundationがある場合/ない場合のコンパイル時分岐があって、 ある場合に、swift-foundationを使うかどうかの実行時分岐があるようだ
12:08 AM
でも 「ない場合」と、「ある場合で使う場合」の実装が違うのはどういうことだ。
12:09 AM
FOUNDATION_FRAMEWORK は、旧があるかどうかじゃなくて、旧版と互換モードってことか・・・?
12:12 AM
A JSONMap is created by a JSON scanner to describe the values found in a JSON payload, including their size, location, and contents, without copying any of the non-structural data. It is used by the JSONDecoder, which will fully parse only those values that are required to decode the requested Decodable types.
12:12 AM
中間データ構造のJSONオブジェクトを作らないっぽいな
12:15 AM
12:16 AM
JSONの構造だけ先にパースして、その構造を高速に巡回するためのオフセットテーブルだけを作るっぽい
12:16 AM
実際の値のデコードは Decodable が要求する時にやる
12:18 AM
なるほどなあ こうやればよかったのか
Avatar
func testBasic() throws { let compareTo = 2 let predicate = Predicate<Object> { // $0.a == compareTo PredicateExpressions.build_Equal( lhs: PredicateExpressions.build_Arg( PredicateExpressions.build_KeyPath( root: $0, keyPath: \.a ) ), rhs: PredicateExpressions.build_Arg(compareTo) ) } try XCTAssertFalse(predicate.evaluate(Object(a: 1, b: "", c: 0, d: 0, e: "c", f: true, g: []))) try XCTAssertTrue(predicate.evaluate(Object(a: 2, b: "", c: 0, d: 0, e: "c", f: true, g: []))) }
12:39 AM
例の Predicate も入ってる
12:39 AM
マクロはまだ入ってないみたいでASTが手書きされてるけどw
12:40 AM
// Hiragana, Katacana -- case not affected test("ァィゥㇳ゚ェォ ヶ゜ アイウエオ", "ァィゥㇳ゚ェォ ヶ゜ アイウエオ") test("ぁぃぅぇぉ ど ゕゖくけこ", "ぁぃぅぇぉ ど ゕゖくけこ")
12:40 AM
typoみつけた→Katacana
Avatar
public struct PredicateBindings { // Store as a values as an array instead of a dictionary (since it is almost always very few elements, this reduces heap allocation and hashing overhead) private var storage: [(id: PredicateExpressions.VariableID, value: Any)] public init<each T>(_ value: repeat (PredicateExpressions.Variable<each T>, each T)) { storage = [] _ = (repeat storage.append(((each value).0.key, (each value).1))) }
12:47 AM
variadic genericsだ
Avatar
Kishikawa Katsumi 4/27/2023 1:10 AM
Swift 5.9が必要なのね。
Avatar
omochimetaru 4/27/2023 1:10 AM
落としてきてXcodeに突っ込めばいいらしいです
Avatar
Kishikawa Katsumi 4/27/2023 1:10 AM
へえ。
1:11 AM
じゃあSwift 5.9を要求するSwift Packageが使えるようなツールチェーンなんだ。
Avatar
omochimetaru 4/27/2023 1:12 AM
ですね
Avatar
Kishikawa Katsumi 4/27/2023 1:12 AM
今まではSwift 5.9入れてもSwift Package ManagerはXcodeからは使えなかった気がする。
Avatar
omochimetaru 4/27/2023 1:12 AM
ツールチェーン入れてもそのへん怪しいがちですね。
Avatar
Kishikawa Katsumi 4/27/2023 1:13 AM
Predicatesって何かしら?新機能でそんなんあったんだ。
Avatar
omochimetaru 4/27/2023 1:13 AM
NSPredicateをモダンにしたいやつ
😻 1
Avatar
Kishikawa Katsumi 4/27/2023 1:13 AM
へえ。Type Safeなクエリが作れるわけね。
Avatar
Kishikawa Katsumi 4/27/2023 1:15 AM
理解した。めっちゃいいやん。
Avatar
omochimetaru 4/27/2023 1:15 AM
arrayをfilterするとかならクロージャで十分なので使い所が難しいですけどね
Avatar
Kishikawa Katsumi 4/27/2023 1:15 AM
この展開方法はネストがすぐ深くなって型推論がタイムアウトになりがちだけど大丈夫かな。
1:16 AM
適当に変数に逃すのかもしれないけど。
Avatar
omochimetaru 4/27/2023 1:16 AM
predicateにするメリットはシリアライズできるので他のマシンとかで実行できるところ・・・
Avatar
Avatar
Kishikawa Katsumi
この展開方法はネストがすぐ深くなって型推論がタイムアウトになりがちだけど大丈夫かな。
omochimetaru 4/27/2023 1:16 AM
現状はマクロが入ってなくてテストコードはマクロ展開後の状態を手書きしているので、 そのようなテストコードが書いてある規模の式なら問題なさそう 複雑な式だと駄目っていうのは起きそうですねえ・・・ (edited)
Avatar
Kishikawa Katsumi 4/27/2023 1:17 AM
リテラルを混ぜるとけっこうすぐ起こせる気がするけどまあ今度試してみよう。
Avatar
PredicatesはORMで使われそうですね
2:21 AM
元々NSPredicateもCoreDataでは良く使ったし
Avatar
Avatar
rintaro
#PowerAssert まででマクロと認識されてしまい、.assert() はその結果に対する普通のメソッド呼び出し
ごめんなさい動作未確認。いずれにしても #ModuleName.macroName できるべきだと思うので、確認してできなかったらIssue あげていただけると。
Kishikawa Katsumi 4/27/2023 7:06 PM
https://github.com/apple/swift-syntax/issues/1594 マクロをモジュール名で修飾できるようにしてほしい、っていうの報告した。
Description The way Swift macros are syntactically defined and their appearance is quite similar to property wrappers and result builders, especially in the case of attached macros. Property wrappe...
iine 3
👏🏻 1
Avatar
Kishikawa Katsumi 4/28/2023 8:57 AM
Since name lookup happens inside semantic analysis, which is done after parsing, I’m moving this to the swift repo.
SwiftSyntaxより後の問題たしかに。
Avatar
omochimetaru 5/9/2023 5:23 AM
Hello, Swift Evolution! Property wrappers have the ability to abstract the storage of a property, including bespoke definite initialization support: @propertyWrapper struct Wrapper { var wrappedValue: T } struct S { @Wrapper var value: Int init(value: Int) { self.value = value // Re-written to self._value = Wrapper(wrappedValue: v...
👀 3
5:23 AM
ホーリー&ドーグから面妖な提案が出た
5:24 AM
パッとみよくわからんかったので後でちゃんと読む
Avatar
これが許されるならジェネリックなsetterも欲しい気がしてきた
11:31 AM
var foo: AnyPublisher<Int, Error> { set { (newValue: some Publisher<Int, Error>) in _foo = newValue.eraseToAnyPublisher() } }
11:31 AM
みたいな
Avatar
omochimetaru 5/18/2023 2:47 PM
読んできた
2:48 PM
property wrapperがついてても、ついてないラップされてるプロパティを初期化できるのは、wrapperの初期化に書き換えてくれるからなんだけど
2:48 PM
そのような挙動を任意のcomputed propertyに対して書けるようにして
2:49 PM
initでcomputed propertyに代入すれば、そのinit accessor内部で初期化するstored propertyを初期化した扱いになる
2:50 PM
これがないと、Ovservableマクロのように、ユーザー定義したstored propertyをcomputed propertyに変換してしまうマクロを使った時に、
2:51 PM
ユーザーはマクロが生成する新しいstored propertyを初期化しないといけなくてめちゃくちゃ使いにくいから
2:51 PM
この機能をいれることでマクロがinit accessorも入れることによって
2:52 PM
ユーザーはstored propertyが消された事を気にしないで普通な感じでinitが書けるというわけだな
Avatar
Avatar
Iceman
var foo: AnyPublisher<Int, Error> { set { (newValue: some Publisher<Int, Error>) in _foo = newValue.eraseToAnyPublisher() } }
omochimetaru 5/18/2023 2:54 PM
これはgetの型はどうなるん?
Avatar
Avatar
omochimetaru
これはgetの型はどうなるん?
getはそのままAnyPublisher
Avatar
Avatar
Iceman
getはそのままAnyPublisher
omochimetaru 5/18/2023 3:00 PM
あーgetより広い型だから成立しそうだ computed propertyはinoutに渡したりもするけど、いったんはgetの型で受けたら動きそう ただ実質的に暗黙の型変換がプロパティの代入だけ導入される感じになりますね
3:01 PM
funcによる手書きのgetterとsetterなら可能な振る舞いだから、良いのかなあ?
Avatar
結局暗黙の型変換になって読みづらくなるかもしれないので言いだしたものの特に欲しくはないですね
Avatar
omochimetaru 5/18/2023 3:04 PM
AnyPublisherという具体例についていえば、existentialの自己準拠機能が入れば、AnyPublisherが不要になってany Publisherを使えば良いので、任意のPublisherがany Publisherへ暗黙変換できるので、それで同じ効果が得られそう (edited)
Avatar
代入とか->演算子の間でガチャガチャ何かが起こるC++を思い出すと避けたい気持ちになる
3:06 PM
existentialの自己準拠はスケジュールあるんでしたっけ?
Avatar
omochimetaru 5/18/2023 3:06 PM
future directionsとかで前向きに出てくるけど具体的なスケジュールの言及はいまのところない
Avatar
なるほど。結構欲しい場面遭遇するので出たら嬉しいですね
wakaru 2
Avatar
omochimetaru 5/18/2023 3:07 PM
Swift6 大計画にも乗ってなかったな・・・
Avatar
omochimetaru 6/15/2023 3:37 PM
Hello Swift community, The review of SE-0400: Init Accessors begins now and runs through June 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 messaging featu...
3:38 PM
400番!
Avatar
Kishikawa Katsumi 6/20/2023 11:40 AM
https://forums.swift.org/t/is-there-a-way-to-programmatically-allow-trust-the-compiler-plugin-to-run-from-the-command-line/65690/2 SwiftのマクロはCIだとコンパイラプラグインの検証を押せなくて失敗するんだけどスキップする方法を教えてもらった。 xcodebuild-skipMacroValidationを渡すか com.apple.dt.Xcode IDESkipMacroFingerprintValidation -bool YES のUserDefaultsを設定すればスキップできる。Xcode Cloudはxcodebuildコマンド使えないから後者でやるしかないね。
You can use defaults write com.apple.dt.Xcode IDESkipMacroFingerprintValidation -bool YES in a script to skip validation of macros from remote dependencies (the equivalent xcodebuild command line flag is -skipMacroValidation).
Avatar
Kishikawa Katsumi 6/20/2023 12:00 PM
-skipMacroValidationman xcodebuildに書いてあるけどUser Defaultsはみんなどうやって見つけてるんやろ。
Avatar
strings
Avatar
SwiftのTask、operation が throws なものまで @discardableResult が付いてるのってどこかで議論されていたりしますか? きちんと処理せずそのまま捨てられることになって微妙なのではと思うのですが…。 https://developer.apple.com/documentation/swift/task/init(priority:operation:)-5k89c (edited)
Runs the given throwing operation asynchronously as part of a new top-level task on behalf of the current actor.
Avatar
Kishikawa Katsumi 6/21/2023 1:26 AM
そうかバイナリの文字列を直接探すのか。
Avatar
あとは、cfprefsdがないキーを検索されたときにwarningだかerrorだかをos_logに出すので、それを監視するみたいな。
Avatar
Kishikawa Katsumi 6/21/2023 1:32 AM
そんなんあるんだ。存在はそれでわかるのか。
Avatar
Avatar
rinsuki
SwiftのTask、operation が throws なものまで @discardableResult が付いてるのってどこかで議論されていたりしますか? きちんと処理せずそのまま捨てられることになって微妙なのではと思うのですが…。 https://developer.apple.com/documentation/swift/task/init(priority:operation:)-5k89c (edited)
This is likely well-known at this point, but I wanted to ask about the rationale for this? Specifically, if this was discussed anywhere else on the forums or documented elsewhere, because I couldn't find it when searching. func someFunction() { Task { try await someThrowingFunction() } } This code swallows the error of someThrowingFun...
Avatar
ありがとうございます!どうにかしたほうがいいよね〜…という声はありつつ、現状 Task { ... } の書き方をそのまま使う場合は SwiftLint で塞ぐしかない、という感じっぽいですね…
Avatar
Aaronだw (もと同僚)
😆 1
Avatar
Avatar
rinsuki
ありがとうございます!どうにかしたほうがいいよね〜…という声はありつつ、現状 Task { ... } の書き方をそのまま使う場合は SwiftLint で塞ぐしかない、という感じっぽいですね…
そうみたいですね。完全無視ではなく何かしらメッセージは出せそうみたいな記載がありましたが、現状は開発側で対策するしかなさそうですね。 (edited)
Avatar
omochimetaru 6/25/2023 6:14 PM
As macros arrive to swift, I would like to discuss a topic about code generation that annoyed me for some time. The main problem is that currently @escaping modifier might be applied only to function types, but, on syntax level, there is no way reliably understand that type is function type or not. Suppose I want to write a macro that generate...
6:14 PM
どれが関数型かわからないからinitマクロ作れない問題、キツイな
Avatar
Kishikawa Katsumi 6/25/2023 6:26 PM
型情報を入れてくれるっていう拡張に期待なんだろうね。
Avatar
別件でこれまさしくハマってました… 型の名前からその型の性質を調べるのが大変
11:41 PM
distributed actorは引数と返り値の型が特定のprotocolを満たしてるか検査できるので、そのような機能をマクロから利用したい
Avatar
Avatar
Iceman
distributed actorは引数と返り値の型が特定のprotocolを満たしてるか検査できるので、そのような機能をマクロから利用したい
omochimetaru 6/26/2023 2:54 AM
distributed actor のその機能、完全に既存の言語機能の表現能力を超えてて、宣言方法も特別だし検査も特別実装なんだよなw
Avatar
Avatar
Kishikawa Katsumi
型情報を入れてくれるっていう拡張に期待なんだろうね。
omochimetaru 6/26/2023 2:57 AM
やっぱりそれが正しい道なんですかね〜。 型情報を提供するAPIの設計がすごく難しいのと、 マクロの評価タイミングは現在は意味解析より前なので、 結構頑張ってもらわないと良いものが出せなさそうだし、時間がかかってしまいそうだ。
Avatar
型情報の解決にはSwiftコンパイラとの通信が必要で、現状ユーザコードとコンパイラドライバが通信するみたいなのはPackagePluginで存在するけど、同様の何かがマクロ側でも必要で、PackagePluginは色々大変そうだったしマクロでも大変そうだ
Avatar
マクロで型使うのかなり大変な気がする
Avatar
Avatar
Iceman
型情報の解決にはSwiftコンパイラとの通信が必要で、現状ユーザコードとコンパイラドライバが通信するみたいなのはPackagePluginで存在するけど、同様の何かがマクロ側でも必要で、PackagePluginは色々大変そうだったしマクロでも大変そうだ
omochimetaru 6/26/2023 2:58 AM
そういう動作アーキテクチャのレベルも結構おお仕事になりますよね。
Avatar
コンパイル前にコンパイル後の成果物要求してるワケなので…
Avatar
Avatar
tarunon
マクロで型使うのかなり大変な気がする
omochimetaru 6/26/2023 2:59 AM
本質的に多くの問題を孕むと思われますw こういう簡単なケースはよくても、変なコーナーケースでややこしい問題が噴出しそう。
Avatar
マクロの対象になったところだけ切り出して部分的に解決、みたいな。で、無限ループが発生して死んじゃう
Avatar
Avatar
tarunon
マクロの対象になったところだけ切り出して部分的に解決、みたいな。で、無限ループが発生して死んじゃう
omochimetaru 6/26/2023 3:02 AM
意味情報はプロパティの型とかから芋づる式に他のファイルに書かれてる情報を辿れるから切り出せ無さそう (edited)
Avatar
マクロ自体の引数に関しては完全にタイプチェックされてからのマクロ展開実行なので、型情報と通信の設計実装さえすればなんとかなる、はず。
Avatar
frameworkが分離されてれば、理論上はimport先の型情報は使えることになりそう
Avatar
けど attached マクロのアタッチ先のdecl やその中のものの型情報は限定的にならざるをえないんじゃないかと思います。 (edited)
Avatar
frameworkの分離が出来ていれば型マクロが使える世界線、良い感じに分離するモチベーションが高まるだろうか
Avatar
omochimetaru 6/26/2023 3:06 AM
なるほど。じゃあ現時点でもマクロに依存した型に依存するマクロ呼び出しは書けないのかな・・・?
3:07 AM
expression macro func foo(_ x: some Observable) ... @Observable class C {} foo(C.init()) // NG?
Avatar
#foo(C.init()) ですかね?それはできるはず。 (edited)
Avatar
omochimetaru 6/26/2023 3:08 AM
あ、そうだ。#foo でした。 (edited)
Avatar
けど @attached(member) macro foo(_: Any) ... @foo(S.init()) struct S { } はどうなんだろうという感じです。
3:10 AM
foo マクロが競合する init() を生成するかもしれない。
Avatar
omochimetaru 6/26/2023 3:10 AM
ややこしいな。 foo の効果によって init が生成されるなら、 暗黙の S.init は存在しないから、不正になっちゃうな。
Avatar
試してないけど、おそらく circular reference だと思います。(じゃなかったらバグであるべき) (edited)
Avatar
omochimetaru 6/26/2023 3:11 AM
そうか。マクロ評価の順序付けさえあれば解決できるケースはまだよくて、 あるマクロの評価前の型情報と、評価後の型情報が、互換性が無いパターンがありえるんですね。 (edited)
Avatar
実際の実装としては macro プラグインからの 型情報リクエストに応じて必要ならオンデマンドでタイプチェックして返す。circular reference 検知したらエラーを返すみたになるのかなと思ってます、が今のところ議論は進んでないですね。
Avatar
omochimetaru 6/26/2023 3:17 AM
そもそものスレッドの件に関しては、 関数ではない型についてちゃっても無害な @escaping があれば解決はするんですよね。
3:18 AM
@escapingIfFunction みたいな。
3:19 AM
memberwise initの生成は個人的にはマクロに期待してた代表的な機能だし、 そういう小汚い対応でもいいから早く実現してほしいw
Avatar
macro 展開されたコードは当然元のソースとは別にパースされるし、タイプチェッカーはそれを知っているので仕様さえ決めればなんとでもなるっちゃなるはず。が、この特定の件に関しては別に「macro の制限だから typealias 使えないです」で良くないかとは個人的には思っちゃう。
Avatar
omochimetaru 6/26/2023 3:29 AM
なるほど・・・ 関数型はタイピング量が多くなりがちだからtypealiasしたくなりがちなんですよね。 でもまあmemberwise initのためにプロパティのところだけ書き下すしてもお釣りは来るなあ。
Avatar
あー、けどローカルだけの制限と考えてたけど、そのモジュールのインターフェイスにも出てきちゃうから混乱しちゃいますね(利用者はプロパティだけ生typeで他はtypealiasされてたら意味わからない)。前言撤回します🙃 (edited)
Avatar
omochimetaru 6/26/2023 3:44 AM
たしかに。publicだと別のつらさが増えますね。
Avatar
Kishikawa Katsumi 6/26/2023 5:50 AM
最初に言ってたtype(of node: SyntaxProtocol)みたいなのがあればだいたいいけると思うんですよね。
5:51 AM
これでカバーできないものは個別に議論していくことになるんじゃないかしら。
Avatar
共有リソースの待ち合わせってstructued concurrencyの仕組みの中だけでは実装できないかな...? unstrucutedな何かが必須かな。 e.g. 複数のcallerから共有の準備ができたら使えるようになるリソースにアクセス、例えばダウンロードは1回だけのリソースに複数箇所からアクセス
7:26 PM
semaphore みたな何かが必要なはずだけど。
Avatar
非同期でリソース初期化するDIコンテナ、がまさに具体の実装になりそう
Avatar
止める必要があるところで継続を取って、準備ができたら継続をresume?
Avatar
async initってもうあるんでしたっけ
Avatar
ですねえ、semaphore 作ってる人わりといて、結果 actor で共有 Task {} の value を待つ, continuation 使うみたいな実装がありました (edited)
Avatar
共有リソースの初期化のasync関数と、置いておく場所はawait propertyにしておけば、外側のclass若しくはactorを初期化するだけで良い気がしましたが、そういう話ではない?
Avatar
二重に初期化されようとした時にセマフォ的なものが必要になりそうという話ですかね
Avatar
そうですね
1:29 AM
URLから画像取ってくるが典型的な気がする
1:29 AM
Data races occur when two separate threads concurrently access the same mutable state. They are trivial to construct, but are notoriously...
Avatar
わはは
Avatar
なかなかに泥臭い
Avatar
どうせ呼び出し側は違うTaskなんだから、わざわざTask.valueでunstructuredにしなくて良いと思います
Avatar
これのImageTask<Image, any Error> になれば良いと思ってました
Avatar
func image(from url: URL) -> Task<Image, Error> ということですか?
Avatar
var cache: [URL: Task<Image, any Error>] ということです。
Avatar
ああ。
1:38 AM
ビデオちょっとだけ進めるとそういう実装になってます
Avatar
あ、ほんとですね
Avatar
どうせ呼び出し側は違うTaskなんだから、わざわざTask.valueでunstructuredにしなくて良いと思います
1:40 AM
ちょっとわかってない...
Avatar
動画の実装、エラーがthrowされるかnilに潰されるかがキャッシュかどうかによって変わるな・・・
1:43 AM
いや読み間違えた
1:45 AM
-> Image? だけどnilが返るケースなさそうな気がする
1:49 AM
確かに
Avatar
async property, stored propertyには使えなかったからダメでしたw
Avatar
もし async let みたいなのがlocal以外で使えれば...
Avatar
We’re excited to announce a new open source package called Swift HTTP Types.
👀 2
❤️ 10
11:42 PM
mac, iOSのURLSessionと、Linuxのswift-nioでHTTP関連の型がそれぞれ存在するの、共通のものにするって。
Avatar
Swift Foundationもそうですけど、ここ最近はマルチプラットフォーム強化が多いですね。 (edited)
Avatar
いい話
Avatar
Kishikawa Katsumi 7/23/2023 7:16 AM
@swift-5.8.1 import Foundation struct Coordinate: Codable { var latitude: Double var longitude: Double } struct Landmark: Codable { var name: String var foundingYear: Int var location: Coordinate } let landmark = Landmark( name: "Tokyo Tower", foundingYear: 1957, location: Coordinate(latitude: 35.658581, longitude: 139.745438) ) let data = try! JSONEncoder().encode(landmark) print(String(decoding: data, as: UTF8.self)) (edited)
Avatar
Avatar
Kishikawa Katsumi
@swift-5.8.1 import Foundation struct Coordinate: Codable { var latitude: Double var longitude: Double } struct Landmark: Codable { var name: String var foundingYear: Int var location: Coordinate } let landmark = Landmark( name: "Tokyo Tower", foundingYear: 1957, location: Coordinate(latitude: 35.658581, longitude: 139.745438) ) let data = try! JSONEncoder().encode(landmark) print(String(decoding: data, as: UTF8.self)) (edited)
{"foundingYear":1957,"location":{"longitude":139.745438,"latitude":35.658581},"name":"Tokyo Tower"} (edited)
Avatar
Kishikawa Katsumi 7/23/2023 7:18 AM
^ これ、iOS 16.xとmacOS Montereyだと {"name":"Tokyo Tower","location":{"longitude":139.74543800000001,"latitude":35.658580999999998},"foundingYear":1957} こういうJSONになる。iOS 17とSonomaだとLinuxと一緒になる。たぶん修正されたんだろうけどこういう突然の変更は困らないかな? (edited)
Avatar
浮動小数点の精度の違いですか? (edited)
Avatar
Kishikawa Katsumi 7/24/2023 2:24 AM
はい。小数が丸められるようになった?って感じです。
Avatar
serializerの問題か、そもそも浮動小数点のIEEE754として確定しない値なのかどっちですかね... (edited)
Avatar
その2つはDoubleの値としては同じみたいですね
3:14 AM
@swift-5.8.1 print(Double(139.74543800000001).description) print(Double(139.74543800000001).bitPattern) print(Double(139.745438).bitPattern) (edited)
Avatar
Avatar
Yuta Saito
@swift-5.8.1 print(Double(139.74543800000001).description) print(Double(139.74543800000001).bitPattern) print(Double(139.745438).bitPattern) (edited)
139.745438 4639120872052549187 4639120872052549187 (edited)
👍 1
Avatar
@swift-5.7.3 print(Double(139.74543800000001).description) print(Double(139.74543800000001).bitPattern) print(Double(139.745438).bitPattern)
Avatar
Avatar
tarunon
@swift-5.7.3 print(Double(139.74543800000001).description) print(Double(139.74543800000001).bitPattern) print(Double(139.745438).bitPattern)
139.745438 4639120872052549187 4639120872052549187
Avatar
swiftのバージョンでここが変わったことを勘ぐったが、違ったw
Avatar
これまではCの何かを使ってたけど、SonomaからSwiftのDouble.description が使われるようになったんじゃないかな (edited)
3:16 AM
SwiftのDouble.descriptionは色々かしこく綺麗に表示する実装が入ってる https://github.com/apple/swift/blob/main/stdlib/public/runtime/SwiftDtoa.cpp
t_naruhodo 2
Avatar
Foundation のJSONEncoder/Decoder は浮動小数点数を一旦 Decimal にしてしまうせいでそう言う問題が起こっていたと思います.新 Foundation (swift-foundation) だと解決してた記憶があります. (edited)
Avatar
なるほど
5:10 AM
import Foundation あるなしの違い...?
Avatar
いや,JSONEncoder/Decoder が Foundation なのでありパターンしかないと思いますよ.
Avatar
そもそもJSONにread/writeしたとき、浮動小数は10進化するときの誤差の関係で、ビットレベルでのroundtripはないものと思っていたけど、あったんですね。
Avatar
JSONは仕様で数字の精度にきまりがないからなあ
12:43 AM
JavaScriptは全部Doubleだけど。
12:43 AM
JSONの数字はお気持ちでパースして精度をきめるしかない
Avatar
数字の精度に決まりがないので、十分な桁数を書き込めば、Doubleがビットレベルで保存できるということですね。
Avatar
ですね
6:31 AM
then 文の実装が作業中だった
6:31 AM
func testNested3() -> Int { if .random() { print("hello") then if .random() { then 1 } else { then 2 } } else { () () then switch Bool.random() { case true: then 0 case false: then 1 } } }
6:32 AM
おそらく、ifやswitchを式モードで使うための文法で、 本文が複数文ではない場合でも、最後の文で return のような感じで then を使うと、それを式の評価値として指定できる。
6:33 AM
これは結構うまいアイデアな気がするぞ。
Avatar
Kishikawa Katsumi 7/26/2023 6:33 AM
これはreturnじゃあかんの?
Avatar
omochimetaru 7/26/2023 6:33 AM
returnとは共存するんだと思います。
Avatar
returnだと関数のreturnとの見分けが問題になりそうな
Avatar
omochimetaru 7/26/2023 6:33 AM
returnは関数を抜ける(if文は中断される)。thenはそのif文の値を指定する。 (edited)
Avatar
let hoge = if { ~ みたいになるんでしょうかね。
Avatar
omochimetaru 7/26/2023 6:35 AM
そうですね、まあ1文ならそれはもう書けるけど。 { ... } を2文以上にできる。 (edited)
Avatar
let foo: Foo = if (...) { ... then xxx } else { ... then yyy } と書くのと let foo: Foo if (...) { ... foo = xxx } else { ... foo = yyy } と書くので、前者がうれしい理由は何?式の中(プロパティの初期化とか)で使えること?それとも、 iffoo の初期化のためのものだとわかりやすいこと?
Avatar
omochimetaru 7/26/2023 6:40 AM
1. 後者は : Foo を省略する余地がない 2. 後者は foo 3回出てきて冗長 3. 前者は、 = の右側が名前foo に依存していないので、コピペして再利用できる(foo 以外の代入に書き換えられる)
6:40 AM
if が foo の初期化のためのものだとわかりやすい
これもあると思いますね。ifの値があることで意味が強くなってると思う。
Avatar
うーん、 1 についてはこんなに長い式で型が書いてないと可読性悪いし、 2 については冗長でも結局 then 書くのも同じくらい面倒だし、 3 についてもこんなに複雑な式をコピペで使い回すことなんてほぼないし・・・。
Avatar
omochimetaru 7/26/2023 6:42 AM
個人的な経験だと、if式を使った後で、デバッグしようとして分岐の中にprintいれたらif式が死んだ事があって(2文になっちゃったから) (edited)
6:42 AM
そういうときにprintいれられるのは便利だなと思う。 (edited)
Avatar
if 式のブレースの中を複数の文にしたいというのはわかるんだけど、そもそも僕は if が文でもそんなに困ってなかったんですよね。 (edited)
Avatar
利便性がぱっと良い判断できない割には真新しい文法が増えるのか〜という感じですね
Avatar
Kishikawa Katsumi 7/26/2023 6:43 AM
then っておそらく一番最後にしか書けないんすよね?returnと一緒じゃないのかな。
Avatar
プロパティの初期化とか、式しか許されてないところで使いたいことはあるけど、それなら ifswitch だけでなく do も対応してほしい(対応してるんだっけ?)
Avatar
Rustの;の有無がthenの無有に対応してるのかな
Avatar
ブロックの最後にのみ書けるところに意義はありそうで、極力代入でなくthenを使いたい感じはしますね (edited)
Avatar
omochimetaru 7/26/2023 6:45 AM
僕はif式の代わりにクロージャ書くことあるけどネストするのが嫌だったので嬉しいですね あと嬉しさだとswitch式のほうが嬉しいです。 func foo() -> Foo { switch self { case .a: return .a case .b: return .b case .c: return .c ... //あと10回ぐらいある } } ↑このパターン、returnのお邪魔度が高い (edited)
Avatar
switch は式になってほしいのわかります。 (edited)
naruhodo 1
Avatar
Avatar
Kishikawa Katsumi
then っておそらく一番最後にしか書けないんすよね?returnと一緒じゃないのかな。
omochimetaru 7/26/2023 6:46 AM
func f() -> Int { let foo = if (cond) { then 1 } else { return 2 // returnなので、printに進まない } print(foo) return foo }
Avatar
きしかわさんの言ってるのは代入だとブロック内のどこでも書けるけど、thenはブロックの末でしか使えないよね?ということでは
Avatar
Kishikawa Katsumi 7/26/2023 6:51 AM
func f() -> Int { let foo = if (cond) { then 1 } else { then 2 // <= これは書けるの? } print(foo) return foo }
Avatar
Avatar
koher
let foo: Foo = if (...) { ... then xxx } else { ... then yyy } と書くのと let foo: Foo if (...) { ... foo = xxx } else { ... foo = yyy } と書くので、前者がうれしい理由は何?式の中(プロパティの初期化とか)で使えること?それとも、 iffoo の初期化のためのものだとわかりやすいこと?
omochimetaru 7/26/2023 6:51 AM
この論点でいうと、 4. thenは必ず末尾に値を出力する文がくる、ifの場合はそうじゃないかもしれないから読みづらくなりうる もありますね。
Avatar
Avatar
Kishikawa Katsumi
func f() -> Int { let foo = if (cond) { then 1 } else { then 2 // <= これは書けるの? } print(foo) return foo }
omochimetaru 7/26/2023 6:51 AM
書けると思いますよ。その場合は foo2 になって、 printされますね。 (edited)
Avatar
むしろ書かないとエラーでは (edited)
Avatar
Kishikawa Katsumi 7/26/2023 6:52 AM
なるほど?
Avatar
Avatar
tarunon
むしろ書かないとエラーでは (edited)
omochimetaru 7/26/2023 6:52 AM
書かないでreturnできる規則もありえると思う。代入を中断して脱出する。 (edited)
Avatar
Kishikawa Katsumi 7/26/2023 6:52 AM
あ、わかったぞ。
Avatar
returnかthenが必須になるんじゃないかなと思う
6:52 AM
returnはつまりthen neverになる、と。
Avatar
omochimetaru 7/26/2023 6:52 AM
throwとtryでも抜けたいね
Avatar
Kishikawa Katsumi 7/26/2023 6:52 AM
thenはcontinue的な制御か。
Avatar
Avatar
tarunon
returnはつまりthen neverになる、と。
omochimetaru 7/26/2023 6:53 AM
その式におけるtypecheckとしてはそういう理屈になりますね。
Avatar
do {} catch {} 式ができたらアツいな
Avatar
Avatar
omochimetaru
throwとtryでも抜けたいね
breakcontinue
Avatar
Kishikawa Katsumi 7/26/2023 6:53 AM
thenとreturnの違いはわかったこういうの書こうとすると必要ですね。
Avatar
Avatar
koher
breakcontinue
omochimetaru 7/26/2023 6:53 AM
あ、そうか。forの中でifをしてるときに、break (continue)とかできたら便利なことがあるかも。 (edited)
Avatar
Avatar
Iceman
do {} catch {} 式ができたらアツいな
if 式よりもほしいですね。
6:55 AM
しかし、 do 式を考えると then というキーワードは微妙かも?
Avatar
omochimetaru 7/26/2023 6:55 AM
@koher の立場だと↓でよくないのですか? let foo: Foo do { foo = try make() } catch { foo = recovered }
Avatar
Avatar
omochimetaru
@koher の立場だと↓でよくないのですか? let foo: Foo do { foo = try make() } catch { foo = recovered }
final class Foo { let x: X = do { ... then x } } これが書きたい
Avatar
omochimetaru 7/26/2023 6:56 AM
あ、catchじゃなくて素のdoか
Avatar
catch があってもいいよ。 try したくなるかもしれないし。
6:57 AM
final class Foo { let x: X = do { ... try ... ... then x } catch { ... then x } } (edited)
Avatar
Avatar
omochimetaru
@koher の立場だと↓でよくないのですか? let foo: Foo do { foo = try make() } catch { foo = recovered }
行数的にあんまりこれと変わらないかもですね。
Avatar
omochimetaru 7/26/2023 6:58 AM
@koher if式が要らなくて let foo: Foo if cond { foo = .. } で十分と感じているなら let foo: Foo do { foo = ... } と書いても十分ではないのですか?
Avatar
そうじゃなくて、プロパティの初期化とか、式しか書けないとこで。
6:59 AM
これまで、クロージャ式即実行で対処するしかなかったところ。
7:00 AM
文が書けるところでスコープ切る目的なら let foo: Foo do { ... foo = ... } はよく書いてますね。
Avatar
omochimetaru 7/26/2023 7:00 AM
なるほど
Avatar
で、どちらのケース(文が使えるところ、式しか使えないところ)にせよ、 if 式がほしいという立場であれば do 式もほしくなるはず。
Avatar
omochimetaru 7/26/2023 7:01 AM
それはそうですね、僕はあったら嬉しい。 (edited)
7:01 AM
いや、でもちょっとまてよ
7:01 AM
if式が使える部分は限定されているんですよ
7:02 AM
7:02 AM
これは今もできないです。
Avatar
Kishikawa Katsumi 7/26/2023 7:03 AM
そうなんよね。
Avatar
omochimetaru 7/26/2023 7:03 AM
だから、現行のif式の延長でのdo式の導入の場合、koherが嬉しいケースは禁止されそうw
Avatar
Kishikawa Katsumi 7/26/2023 7:03 AM
引数に書きたいとかはある。
Avatar
え、そうなのか。式なのになぜ😂
7:08 AM
まあいずれにせよ、 if 式が使いたい人にとっては、文が使える場所で let let foo: Foo = do { ... then ... } と書きたくなるニーズがあるはずで、そうすると then というキーワードは適してるのかな?別に変ではない?
Avatar
Kishikawa Katsumi 7/26/2023 7:10 AM
do ... thenが英語として自然か?って話ですか?
Avatar
Avatar
koher
え、そうなのか。式なのになぜ😂
omochimetaru 7/26/2023 7:13 AM
https://github.com/apple/swift-evolution/blob/main/proposals/0380-if-switch-expressions.md#detailed-design
There are of course many other places where an expression can appear, including as a sub-expression, or as an argument to a function. This is not being proposed at this time, and is discussed in the future directions section.
だめな理由ははっきりとは書いてないなあ、いったん狭い範囲で導入する、という感じですね。 Future Directionsのほうに、full expression化するとこれまでの文法とコンフリクトしてsource breakingになるケースの言及はありますね。
Avatar
full expression化するとこれまでの文法とコンフリクトしてsource breakingになるケース
なるほどー。
7:30 AM
気になるのは、 do 式が返す値に使うキーワードが then で適切なのかというところ。
7:30 AM
よさそうな気もするし、条件を受けてないと変なような気もする。ネイティブの感覚がわからない。
Avatar
omochimetaru 7/26/2023 7:30 AM
まあthen文についてはまだforumにpitchすら投げられていない、実装を盗み見てるだけなので (edited)
7:31 AM
thenキーワードで提案されるかどうかもわからない
Avatar
GPT-4に聞いてみた。 do then はちょっと違和感があるっぽい。 https://chat.openai.com/share/84f670d0-dc65-473c-b83b-d1cc2c6f08d2
Avatar
omochimetaru 7/26/2023 7:40 AM
それっぽい代案出せるのえらいなあ
7:40 AM
でも resultoutput は既存のローカル変数と衝突しまくりそうだ
Avatar
ちゃんとプログラミングの文脈で returnyield がダメなのをわかってくれるから話が早い。
Avatar
Avatar
omochimetaru
でも resultoutput は既存のローカル変数と衝突しまくりそうだ
give は衝突しにくそうに思った。
Avatar
omochimetaru 7/26/2023 7:42 AM
ですね
Avatar
Forum に then の話が出てきたら、 if 式の Proposal に do 式あるけど、 then だと微妙じゃない? give とかどう?って書いてみればいいのかな。
Avatar
Kishikawa Katsumi 7/26/2023 7:43 AM
私はemitいいと思うな
Avatar
emit なら変数名には使われなさそうだから(メソッド名ならありそうだけど)、なんとかパースできそう?
7:44 AM
for とか in とかそんな扱いじゃなかったっけ?
Avatar
omochimetaru 7/26/2023 7:44 AM
まあ衝突する場合は バッククォートすればいいって感じにはなりそうだから、たまに衝突するのはセーフそう
Avatar
ruby経験者なのでifだろうがなんだろうが式になると嬉しい
Avatar
omochimetaru 7/31/2023 3:14 PM
Hey all, I've been playing around with a design for function body macros, i.e., attached macros that can introduce, augment, or change the body of a function. Motivating examples include things like: @Remote // synthesizes a function body that does an RPC func f(a: Int, b: String) async throws -> String @Logged // adds logging on entry/exit...
👀 1
3:14 PM
関数本文つくったり、関数をラップした関数にするやつの話が出てきた
3:15 PM
型検査のタイミング?とかで悩ましい事があるらしい
Avatar
Kishikawa Katsumi 7/31/2023 3:51 PM
Swiftの6に入るのかな。5.9には間に合わんよな。
Avatar
5.10かも
Avatar
Kishikawa Katsumi 8/1/2023 1:01 AM
早めに来るとうれしいね。
Avatar
omochimetaru 8/1/2023 2:47 AM
下書きのほうに悩ましい事について詳しく書いてありそうなので後で読んでみる (edited)
7:24 AM
マクロが展開した結果として、ローカル変数が導入されるようなパターンで、
7:24 AM
マクロ展開前に型チェックすることができない
7:26 AM
なのでコード補完とかできない、みたいな話か・・・?展開してから処理するのは難しいのかな、よくわからなかった
Avatar
expression macrosにもtype checkについて数点書かれてたけど、現状はfuncの引数みたいに型を明示的に書くから型チェックできたり、それ以外だと型が不明でも困らないケースしかないのかも
The main complexity of this future direction is in defining the APIs to be used by macro implementations to describe the Swift type system and related information. It would likely be a simplified form of a type checker's internal representation of types, but would need to remain stable. Therefore, while we feel that the addition of type information is a highly valuable extension for expression macros, the scope of the addition means it would best be introduced as a follow-on proposal.
https://github.com/apple/swift-evolution/blob/main/proposals/0382-expression-macros.md
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 8/2/2023 3:32 AM
expression macroと違ってfunc macroは関数本文だからマクロ適用前の型チェック要らなそうだよね (edited)
3:33 AM
というか、「既存の関数本文」の型ってなんだ?そんなものはないのか。
3:33 AM
@attached(body) macro Remote() = #externalMacro(...) @attached(preamble) macro Logged() = #externalMacro(...) @attached(body) macro Traced(_ name: String? = nil) = #externalMacro(...)
3:33 AM
なさそうだ。
Avatar
On the other hand, type-checking the function bodies before macro expansion has other issues. For one, the declarations to which an attached macro is attached are generally not type-checked at all prior to expansion, so type-checking the body prior to expansion would be a departure from that. Additionally, type-checking a function body can be expensive at compile time, and doing that work twice (once for the function body as-written, once after expansion) could increase compile times unacceptably. Finally, type-checking the function body before macro expansion limits what can be expressed by function body macros.
関数本文の型チェックは何故か必要そうだね。attached macroは展開前に型チェックしてなくて展開後に型チェックしててOKだけど、func macroは展開前と後の2回型チェックしたいらしい。
3:49 AM
型チェックというかコンパイルと書いてるから、型推論とか最適化の何かが関数本文に必要という感じなのかな
Avatar
omochimetaru 8/2/2023 3:49 AM
なんで2回必要なんだろうなあ 展開後だけではだめなのか
Avatar
3週間ほど休暇を取っていたのでまったく追えていないのですが、プロポーザルを読む限り:
  • マクロの引数がタイプチェックされるのと同様に、ボディも展開前タイプチェックするかどうかは完全にデザイン選択の問題です。 タイプチェックしたほうが嬉しい場合もあるということですね
if they are fully type-checked prior to expansion, then the bodies are easier to reason about for programmers and also for tools.
  • プロポーザルで述べられている関数ボディマクロは3種
1) 元のボディがない → 展開前タイプチェック不要 @attached(body) macro Remote func f(a: Int, b: String) async throws -> String 2) 元のボディの前に何かを挿入する → 展開前タイプチェックする @attached(preamble) macro Logged func g(a: Int, b: Int) -> Int { return a + b } 3) 元のボディを書き換える → 展開前タイプチェックしない @attached(body) macro Traced @Traced("Doing complicated math") func h(a: Int, b: Int) -> Int { return a + b }
  • 3 のパターンにおいて、展開前にタイプチェック_しない_ことでマクロで追加される変数名を使えるなどの利点がある一方、 その関数ボディ内でのコード補完や Jump to Definition などの IDE 機能が制限される可能性が高いです。
展開してから処理するのは難しいのかな
コンパイラはマクロの実装が元のボディの要素を展開後のどこに配置したのか、そもそも利用したのかの知識がありません。なので仮に @SomeBodyMacro func foo(a: Int, b: Int) { expr }func foo(a: Int, b: Int) { expr let a: String = "" expr } に書き換えられるマクロがあったとき、非常に恣意的な例ですが、 @SomeBodyMacro func foo(a: Int, b: Int) { a.<HERE> } みたいなコード補完だと、a が Int なのか String なのかわからない、みたいな話です。
Avatar
omochimetaru 8/6/2023 6:39 AM
あーーそうか〜〜
6:39 AM
展開後だけ常に考えたらいいと思ってたけど、自由bodyマクロだと、展開後のコードとエディタ上にある展開前のコードの対応関係が取れないんですね (edited)
6:43 AM
極端な話切り刻んで並び替えるようなマクロもありえるし。
Avatar
その通りです。コード補完実装担当者としては(不正確かもしれないけど)展開前ボディでタイプチェックしてなんとか候補を出すしかないと考えています。
Avatar
omochimetaru 8/6/2023 6:45 AM
ローカル変数が注入されるタイプのマクロとかは、マクロ側でその変数の型情報とかを(peerマクロとかの名前のprefixとかみたいに)ヒントとして宣言するようなのが良さそう
6:46 AM
でも分岐の片方だけある変数が使えるとか、表現できないパターンは無限にあるな
6:46 AM
↑の挟んで2回出てくるパターンもそうですね
t_desune 1
Avatar
ほとんどの場合は展開前コードだけで実用的にはなるんじゃないかと思いますが、ローカル変数注入以外にも、 func foo(x: Int) { print(x) }func foo(x: Int) { wrapper { (x: Wrapped<Int>) in print(x) } } に展開されるみたいなときに、不正確になる可能性が高いですね。
Avatar
Avatar
omochimetaru
5.10かも
Kishikawa Katsumi 8/24/2023 3:25 PM
Swift 5.10 Release Process This post describes the release process, and estimated schedule for Swift 5.10. Snapshots of Swift 5.10 Downloadable snapshots of the Swift 5.10 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. O...
Avatar
omochimetaru 8/24/2023 5:19 PM
おー、5.10出るのか〜
Avatar
omochimetaru 9/8/2023 7:34 AM
Hello Swift community, The review of SE-0408 "Pack Iteration" begins now and runs through September 19th, 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 messaging...
7:35 AM
for <name> in repeat <pack> で可変長型パラメータをイテレートできるようになるらしい。
7:38 AM
直感的にはこれでだいぶいろんな事ができるようになりそう
Avatar
タプルを配列に変換する事ができるようになりそうですね…
Avatar
omochimetaru 9/8/2023 8:02 AM
そうですね。
8:03 AM
でもタプルの前後をひっくり返すとかは無理そう
😔 1
Avatar
タプルの配列化は手で全部要素書くか、Mirror使わないとだったのが気持ち悪かったので便利になりそう…
Avatar
ObjC側で公開してないメソッドと同名のメソッドをSwift側で@objc付けて実装するとoverride出来ちゃうのを見つけたんですけど、これって仕様ですか?
Avatar
コード欲しいです
Avatar
class ViewController: UIViewController { @objc func _contentOrObservableScrollViewForEdge( _ edge: NSDirectionalRectEdge ) -> UIScrollView? { nil } } こういうのができちゃう
7:17 AM
_contentOrObservableScrollViewForEdgeはViewControllerの中にあるUIScrollViewのcontentOffsetが変わるとcontentScrollView(for edge: NSDirectionalRectEdge) -> UIScrollView?の直前で呼ばれる
Avatar
ObjCクラスのメッセージディスパッチの仕組みを考えると、やむを得ない仕様だと思います
7:23 AM
ObjCの時も、UIWebViewをoverrideして、「たまたま」アンスコ始まりのメソッドを書くと「何故か」UIKitから呼ばれることはあったので (edited)
😂 3
7:24 AM
同じ現象に思う。overrideの記号はあくまでswiftクラスのためのものじゃないかな
Avatar
それってOjbCからでもoverrideできたりしませんか?
Avatar
たまたま何故かww
Avatar
解ってて言ってますよw(念為) ObjCでも同じ動きすると思います。dynamicがobjcを内包してそうな気はしますね
Avatar
元のメソッド消えても急死したりしないし、たまたま偶然同じメソッドを定義するのは結構便利かもしれない
Avatar
それでボコボコにした動きを前提としてると、呼ばれなくなって崩壊するのはちょいちょいありますねw window.openをフックしていて更新起因で死んだ記憶がある…
Avatar
あー、あとoverrideしてもsuperを呼ぶ手段が無いから別の処理が足されると壊れるのか
Avatar
https://developer.apple.com/documentation/objectivec/1456716-objc_msgsendsuper 間違えたフリしてこれを使うと、呼べますねw swiftからは無理ですが
Sends a message with a simple return value to the superclass of an instance of a class.
🤭 1
9:32 AM
プライベートメソッドに手を出すときに急に知能指数が下がるの、古めかしいiOSエンジニア仕草だと思う
😂 2
Avatar
まだ pitch までしか出たことがないと思いますが,typed throws の実装が始まってました. https://github.com/apple/swift/pull/68629
Start implementing typed throw specifiers with the syntax throws(X). There are a large number of tasks involved in such a feature; this pull request covers the parsing and type checking aspects. ...
t_oltsu 8
Avatar
Embedded Swiftで使いたいというモチベーションみたいですね👀
I've become interested in typed throws because it's a good direction for error handling in Embedded Swift, and have started on an implementation
https://forums.swift.org/t/status-check-typed-throws/66637/20
(edited)
Yes, I think it is. I've become interested in typed throws because it's a good direction for error handling in Embedded Swift, and have started on an implementation. I'd be happy to work with other folks on the proposal and design. @minuscorp had a good start on a proposal that captures a lot of the motivation, and @John_McCall laid out much of...
Avatar
The types of thrown errors will be restricted in some manner, because thrown errors are of existential type any Error (which is disallowed by the prior item).
https://github.com/kubamracek/swift-evolution/blob/embedded-swift/visions/embedded-swift.md#embedded-swift-language-subset
(edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - kubamracek/swift-evolution
Avatar
typed throwsって組み込み的にどう嬉しいんでしょうかね?
11:12 PM
Resultでは解決できない課題がある?
Avatar
Avatar
Iceman
typed throwsって組み込み的にどう嬉しいんでしょうかね?
ヒープメモリのメモリ消費とかアクセス速度を気にしてるとか? ResultでいろいろやるとswitchとかflatMapが増えてthrowsに比べると制御を書くのが大変ということではないかなあ
11:16 PM
typed throwでもその辺のABIは変わらない気がするけど・・・
Avatar
shizさんの貼ってくれたリンク先に書いてありましたね、そもそもexistential がない世界観なのか
Avatar
えっ、それはすごいな 組み込みSwiftそんな踏み込んだ方向目指してるのか
Avatar
読んでるとめちゃくちゃ制約多くてかなり書き味が違うSwiftになりそう、これならzigとかでいいんじゃないかな
Avatar
ダイナミックなもの全部潰してるな
Avatar
Avatar
Iceman
読んでるとめちゃくちゃ制約多くてかなり書き味が違うSwiftになりそう、これならzigとかでいいんじゃないかな
zigしらんのでチラッと見てきたけど、Swiftと比べるとジェネリクスはあるけどプロトコルがないっぽいのが気になった。
Avatar
any無い世界凄いな
Avatar
Goalの最後に
The Embedded Swift language subset should stay very close to “full” Swift,
と書いてあるものの、次のlimitation見ると結構違ってくるのではないかなという印象です。
Avatar
Typed throws嬉しいは嬉しいけど、Swift Evolutionsにないよね…
Avatar
Swift Evolutionsにないよね…
まだpitchが出てくるような段階に辿り着いていないという認識でした。最後のスレッドがこれだった気がします。 https://forums.swift.org/t/precise-error-typing-in-swift/52045
Introduction When error handling was added to Swift in 2015, it intentionally did not allow the expression of precise error types: either a function cannot throw, or it can throw any Error. The error-handling rationale I wrote, which uses an awful lot of words to describe most aspects of the design, gives this one pretty short shrift: There ar...
t_naruhodo 2
Avatar
omochimetaru 9/20/2023 2:28 PM
Start implementing typed throw specifiers with the syntax throws(X). There are a large number of tasks involved in such a feature; this pull request covers the parsing and type checking aspects. ...
2:29 PM
Yes, I think it is. I've become interested in typed throws because it's a good direction for error handling in Embedded Swift, and have started on an implementation. I'd be happy to work with other folks on the proposal and design. @minuscorp had a good start on a proposal that captures a lot of the motivation, and @John_McCall laid out much of...
Avatar
このスレッド今すごい勢いで伸びてる
10:00 PM
typed errorの話が動きそうだから意見のある人達が書き込んでる
t_waiwai 1
Avatar
複数のエラーをthrowするのは微妙だろうなぁ。Unionを導入することになっちゃうし、エラー型が爆発してJava状態になってしまう。typed throws使いたいなら各レイヤーでそれらのレイヤーなりの意味を持ったエラー型に読み替えるべき。 で、ライブラリはそれをする労力を払う価値はあるけど、アプリケーションでは多くの場合コストに見合わないから、アプリではuntyped throwsを使うっていう棲み分けにだろうなぁ。
Avatar
ライブラリとアプリというより、ある関数の機能の関心が、その動作に含まれるローレベルの動作に含まれるかどうか、ってことだと思うんですよね
11:26 PM
例えば func callAPI(request:) async throws -> Response みたいな場合、
11:26 PM
関心の粒度はAPIの仕様の粒度であって、
11:26 PM
それがどういうネットワークライブラリ(URLSession? async-http-client?) なのか、はたまたネットワークじゃなくてスタブに繋がっているのか
11:27 PM
みたいなその実現方法までは関心をもたない、抽象化してしまったほうが
11:27 PM
便利でもある、みたいな。
11:27 PM
エラー型を正確に列挙しようとすると、必然的にその実現方法に強く依存したインタフェースになってしまうので
11:27 PM
関心を上層に限定して抽象化することができなくなる。 (edited)
11:30 PM
他にもこういう topologicalSort みたいな純粋なロジックの関数とかは、下層の実現方法の選択肢という概念がそもそもあてはまらなくて、ありえる失敗が固定されてるから、エラー型を列挙するのと相性が良い (edited)
Avatar
そもそも列挙されていないと何のErrorが飛んでくるかわからないし、catchしてもせいぜいログ残して握りつぶすぐらいしかできない… 飛んでくるErrorに自分が関心があるかすら分かりづらいから基本的に列挙されてほしい気がします。 (edited)
Avatar
Avatar
omochimetaru
ライブラリとアプリというより、ある関数の機能の関心が、その動作に含まれるローレベルの動作に含まれるかどうか、ってことだと思うんですよね
理想的には、すべてのレイヤーでそのレイヤーのセマンティクスで抽象化されたエラー型が定義され、そのエラー型で throw されるべきだと考えています。それであれば上層が下層の実装に依存することはなくなります。 でも、その型付けにはコストがかかり、多くの場合、アプリでは一回か多くても数回程度しか利用しないことが多いので、型付けのコストが価値を上回らないと考えています。ライブラリの場合は無限回利用され得るのでコストに見合う価値があります。
Avatar
Avatar
koher
理想的には、すべてのレイヤーでそのレイヤーのセマンティクスで抽象化されたエラー型が定義され、そのエラー型で throw されるべきだと考えています。それであれば上層が下層の実装に依存することはなくなります。 でも、その型付けにはコストがかかり、多くの場合、アプリでは一回か多くても数回程度しか利用しないことが多いので、型付けのコストが価値を上回らないと考えています。ライブラリの場合は無限回利用され得るのでコストに見合う価値があります。
そのレイヤーのセマンティクスで抽象化されたエラー型が定義され
例えばAPI呼び出しなら、通信のレベルと、JSONを処理するレベル、APIに応じたバリデーションのレベル、みたいに整理する、という事でしょうか? そうだったとして、この抽象化されたエラー型の中に、具体的な実装に依存したエラー型が渡せるように、 any Error が混ざり込みませんかね? // こういうのは列挙できたとしても・・・ enum ProtocolError { case brokenJSON case invalidFormat(String) ... } enum APICallError { case protocolError(ProtocolError) // ↓こっちは実装変更に対応しようとすると列挙できない case networkError(any Error) }
Avatar
Avatar
trickart
そもそも列挙されていないと何のErrorが飛んでくるかわからないし、catchしてもせいぜいログ残して握りつぶすぐらいしかできない… 飛んでくるErrorに自分が関心があるかすら分かりづらいから基本的に列挙されてほしい気がします。 (edited)
例にあげたような上流の関数の場合、仮に列挙されていたとしても、 結局のところログを出すかユーザにメッセージを出すか、ぐらいしかできることがなくて、 いくらかのパターンの場合にはリトライの選択肢がある、ぐらいになると思います。
Avatar
Avatar
omochimetaru
そのレイヤーのセマンティクスで抽象化されたエラー型が定義され
例えばAPI呼び出しなら、通信のレベルと、JSONを処理するレベル、APIに応じたバリデーションのレベル、みたいに整理する、という事でしょうか? そうだったとして、この抽象化されたエラー型の中に、具体的な実装に依存したエラー型が渡せるように、 any Error が混ざり込みませんかね? // こういうのは列挙できたとしても・・・ enum ProtocolError { case brokenJSON case invalidFormat(String) ... } enum APICallError { case protocolError(ProtocolError) // ↓こっちは実装変更に対応しようとすると列挙できない case networkError(any Error) }
はい、その場合は any Error が混ざってしまうか、実装に依存した型がassociated valueに現れると思います。
Avatar
Avatar
koher
はい、その場合は any Error が混ざってしまうか、実装に依存した型がassociated valueに現れると思います。
そこの any Error には何が含まれうるか静的にわからないわけですけど、 エラーハンドリングの観点でば、「ネットワークのエラーです (詳細情報はあったりなかったり)」って初手の分類はできるから便利・・・?
11:50 PM
ライブラリの利便性のためにネットワーク層は注入可能にしたい、みたいな状況がありえて、そうなると列挙不可能なんですよね。
Avatar
Avatar
omochimetaru
例にあげたような上流の関数の場合、仮に列挙されていたとしても、 結局のところログを出すかユーザにメッセージを出すか、ぐらいしかできることがなくて、 いくらかのパターンの場合にはリトライの選択肢がある、ぐらいになると思います。
上層のエラーをハンドリングする際に、下層のエラーの詳細に応じてハンドリングすることが誤りではないですか?それぞれの層に準じたセマンティクスがあるはずで、その層のセマンティクスではなく、下層のエラーに対してハンドリングをするのは、カプセル化された実装の中身が漏れ出しているのでは?
11:52 PM
ただ、理想的にはそうやってそれぞれの層におけるセマンティクスでエラーを型付けするのが正しいと思うけど、それにはコストがかかるので、現実的にはそのコストに見合うところでしかそれはできないだろうと考えています。
Avatar
Avatar
koher
上層のエラーをハンドリングする際に、下層のエラーの詳細に応じてハンドリングすることが誤りではないですか?それぞれの層に準じたセマンティクスがあるはずで、その層のセマンティクスではなく、下層のエラーに対してハンドリングをするのは、カプセル化された実装の中身が漏れ出しているのでは?
例えば Decodable が投げる DecodingError がキャッチできたとしても、内部処理のどのタイミングで発生したのかわからん、みたいな状況は、その指摘に該当するかなと思います。 サーバーから返ってきたJSONが仕様と違った、だけとは限らなくて、内部のキャッシュシステムが持ってるメタデータが壊れていた、のかもしれない。みたいな。 (edited)
11:56 PM
「層による意味付け」がされていれば、 enum E { case responseDecodingError(DecodingError); case cacheSystemError(any Error) } みたいになっててわかりそう。
Avatar
Avatar
omochimetaru
例にあげたような上流の関数の場合、仮に列挙されていたとしても、 結局のところログを出すかユーザにメッセージを出すか、ぐらいしかできることがなくて、 いくらかのパターンの場合にはリトライの選択肢がある、ぐらいになると思います。
おっしゃるとおり取れる選択肢は少ないとは思いますが、 UXを考えて実装を作り込もうと思ったときは大事になると考えています。 単純なリトライだけでなく「タイトル被ってるから変えてね」と入力画面に戻すとか色々細かくやるときなど。 実際そこまでやることあんまりないしコストパフォーマンス釣り合ってないとかはあるかもしれませんが、使う側としてはできるのであればあっただけよいかなと。 「そのError出るの知ってたらcatchで対応してたよ…(いちいち全部コード読まないと分からないの…?)」というのがなくなってほしい。 (edited)
Avatar
Avatar
trickart
おっしゃるとおり取れる選択肢は少ないとは思いますが、 UXを考えて実装を作り込もうと思ったときは大事になると考えています。 単純なリトライだけでなく「タイトル被ってるから変えてね」と入力画面に戻すとか色々細かくやるときなど。 実際そこまでやることあんまりないしコストパフォーマンス釣り合ってないとかはあるかもしれませんが、使う側としてはできるのであればあっただけよいかなと。 「そのError出るの知ってたらcatchで対応してたよ…(いちいち全部コード読まないと分からないの…?)」というのがなくなってほしい。 (edited)
「タイトル被ってる」みたいなエラーは便利なので列挙したいですね。 (1)「含みうるエラー」を伝えるために列挙する事と、 (2)「ありえる全てのエラー」を完全に列挙する事にギャップがあると考えています。 (1)は便利だけど、typed throwsで(2)を目指してしまうと、先述のように抽象化できないとか、 どうせほぼ意味のある処理は作れない下層の異常が飛んでくる、のに、そいつらを列挙する労力が無駄にかかりすぎてしまう。
t_naruhodo 1
12:01 AM
僕は最近は (1) だけ実現するために func login() async throws -> Result<LoginResult, LoginError> みたいにやってます。 (edited)
12:02 AM
そのレイヤーで関心があって、特別なハンドリングがありえるエラーはResultで明記して、その他の下層のエラーを流し込むために throws も付けておく。 (edited)
Avatar
現実的なユースケースをみて無視されてるエラーって今でもたくさんありますよね Intのオーバーフローとか、OOMとか。それらのように無視させるエラーというのは一定数確実に存在していて、やはり型をつけたいエラーは人間が実装するビジネスロジック内のごく少数に限られると思うんですよね
Avatar
Avatar
omochimetaru
僕は最近は (1) だけ実現するために func login() async throws -> Result<LoginResult, LoginError> みたいにやってます。 (edited)
これはわかるんですが、戻り値で扱うと戻り値がない場合にエラーハンドリングを強制させづらくないですか?無視しても警告が出るから良い?
Avatar
Avatar
Iceman
現実的なユースケースをみて無視されてるエラーって今でもたくさんありますよね Intのオーバーフローとか、OOMとか。それらのように無視させるエラーというのは一定数確実に存在していて、やはり型をつけたいエラーは人間が実装するビジネスロジック内のごく少数に限られると思うんですよね
Universal ErrorとRecoverable Errorは区別されていて、その上でtyped throwsが議論の対象としているのはRecoverable Errorだと思います。
Avatar
(1)「含みうるエラー」を伝えるために列挙する
これはエラーを提供する側とエラーを受け取って処理する側のコミュニケーションコストが高くなる場合もあるかなと感じることがあります。 例えば、決済システムでサーバから返ってくる大量のエラーコードを、起こりうるエラーに変換してthrowする共通フレームワークがある場合、そのフレームワークを利用する側が「実はこういうエラーが欲しい」という要求をすると、実装されるまでの時間がかかったりなどのコストが結構かかることがあって悩むことがありますね...
(edited)
Avatar
Avatar
koher
これはわかるんですが、戻り値で扱うと戻り値がない場合にエラーハンドリングを強制させづらくないですか?無視しても警告が出るから良い?
はい、Resultを使う問題点は普通にあります。 あと、 LoginErrorが throws のほうに流し込まれる変なケースも頭がいたいです。 だから、これと同じことが typed throws だけでできたら良いなあと今思いました。
Avatar
Avatar
omochimetaru
はい、Resultを使う問題点は普通にあります。 あと、 LoginErrorが throws のほうに流し込まれる変なケースも頭がいたいです。 だから、これと同じことが typed throws だけでできたら良いなあと今思いました。
そうすると、一般的なunionは避けるにしても、 any Error だけは特別に throw できたらうれしいってことになりそうですね・・・。
Avatar
enum LoginError { case ... case other(any Error) } ↑まあこれを書いたらいいのかな?
Avatar
Javaの検査例外・非検査例外に似てるけど、untypedでもハンドリングが強制される点が異なる。
Avatar
型にできそうだな enum PartialExplicitError<E> { case explicit(E) case implicit(any Error) } func login(...) async throws(PartialExplicitError<LoginError>) -> LoginResult (edited)
Avatar
フレームワークを利用する側が「実はこういうエラーが欲しい」
利用者によって関心が異なり、「回復すべきか?」ということすら利用者次第なの難しいですね… (例えばOOMだってシステムプログラミングなら対応したいかもしれない。Embedded Swift文脈から来たのはそういうこと?)
(edited)
Avatar
Avatar
koher
そうすると、一般的なunionは避けるにしても、 any Error だけは特別に throw できたらうれしいってことになりそうですね・・・。
例にあげたtopologicalSortのように、本当に列挙しきりたくてそれが可能で、すり抜ける下層とかも無いこともあるんで、 any Error すりぬけがあるか、ないか、だけ書き分けられると便利だったりするかなあ
👍 1
Avatar
しかもそれに対応していくと特定の利用者限定のエラーが生まれてしまう可能性もあり。case others(any Error)などを作成して「あとは任せた」でいいのかもしれないですが。 (edited)
Avatar
Avatar
shiz
(1)「含みうるエラー」を伝えるために列挙する
これはエラーを提供する側とエラーを受け取って処理する側のコミュニケーションコストが高くなる場合もあるかなと感じることがあります。 例えば、決済システムでサーバから返ってくる大量のエラーコードを、起こりうるエラーに変換してthrowする共通フレームワークがある場合、そのフレームワークを利用する側が「実はこういうエラーが欲しい」という要求をすると、実装されるまでの時間がかかったりなどのコストが結構かかることがあって悩むことがありますね...
(edited)
「このエラーコードの場合のcaseも追加したい」みたいな状況は、コーディングとしては簡単なはずで、 それが面倒になるのは開発体制の問題な気がしました 例えばそのフレームワークをフォークしてたらすぐ対応できますよね
Avatar
Avatar
omochimetaru
例にあげたtopologicalSortのように、本当に列挙しきりたくてそれが可能で、すり抜ける下層とかも無いこともあるんで、 any Error すりぬけがあるか、ないか、だけ書き分けられると便利だったりするかなあ
こんな感じで // any Errorを許すアスタリスク func login(...) async throws*(LoginError) -> LoginResult
Avatar
Avatar
trickart
フレームワークを利用する側が「実はこういうエラーが欲しい」
利用者によって関心が異なり、「回復すべきか?」ということすら利用者次第なの難しいですね… (例えばOOMだってシステムプログラミングなら対応したいかもしれない。Embedded Swift文脈から来たのはそういうこと?)
(edited)
利用者によって関心が異なるのはその通りだと思います。index out of boundsですら、Logic Failureとして扱われていて多くのケースではそれが適当だけど(たとえば、クイックソートを実装するときに毎回index out of boundsのハンドリングを強制されると辛いとか)、場合によってはハンドリングしたいこと(番兵のように使いたいとか)もありますし。 なので、基本は多くの想定ユースケースに合わせながら、Universal ErrorやLogic FailureをRecoverable Errorに昇格させる手段が提供されるといいんだと思います。
👀 1
Avatar
Avatar
omochimetaru
「このエラーコードの場合のcaseも追加したい」みたいな状況は、コーディングとしては簡単なはずで、 それが面倒になるのは開発体制の問題な気がしました 例えばそのフレームワークをフォークしてたらすぐ対応できますよね
例えばそのフレームワークをフォークしてたらすぐ対応できますよね
あ、これは内部で開発しているフレームワークを想定していてforkは想定していませんでしたmm
開発体制の問題な気がしました
そうですね。コミュニケーションに時間がかかるなどの面に関してはこれはすごい感じますw
(edited)
Avatar
Avatar
koher
Universal ErrorとRecoverable Errorは区別されていて、その上でtyped throwsが議論の対象としているのはRecoverable Errorだと思います。
そう、だから何でもかんでもエラーに型をつけることは、Universal Errorの多くをRecoverable Errorに持ち込んで手間が増える結果になってしまうと思うんですよね
Avatar
Avatar
omochimetaru
型にできそうだな enum PartialExplicitError<E> { case explicit(E) case implicit(any Error) } func login(...) async throws(PartialExplicitError<LoginError>) -> LoginResult (edited)
これRustで(たぶん)よくある形ですよね
👀 1
Avatar
Avatar
Iceman
そう、だから何でもかんでもエラーに型をつけることは、Universal Errorの多くをRecoverable Errorに持ち込んで手間が増える結果になってしまうと思うんですよね
Universal ErrorやLogic Failureにtyped throwsで型を付けることはないんじゃないでしょうか?これまでRecoverable Errorに型を付けられなかったのを付けられるようにしたいという、Recoverable Errorに限定した話ではないですか?
Avatar
Avatar
koher
Universal ErrorやLogic Failureにtyped throwsで型を付けることはないんじゃないでしょうか?これまでRecoverable Errorに型を付けられなかったのを付けられるようにしたいという、Recoverable Errorに限定した話ではないですか?
それでいうと僕の発言は https://discord.com/channels/291054398077927425/291054454793306112/1154199388881694790 を踏まえた上なので、Recoverable Errorに限定してない状況の想定でした (edited)
Avatar
Avatar
Iceman
それでいうと僕の発言は https://discord.com/channels/291054398077927425/291054454793306112/1154199388881694790 を踏まえた上なので、Recoverable Errorに限定してない状況の想定でした (edited)
ああ、なるほど、そこの会話がつながってたんですね。
Avatar
Avatar
shiz
例えばそのフレームワークをフォークしてたらすぐ対応できますよね
あ、これは内部で開発しているフレームワークを想定していてforkは想定していませんでしたmm
開発体制の問題な気がしました
そうですね。コミュニケーションに時間がかかるなどの面に関してはこれはすごい感じますw
(edited)
まあ、そのシナリオだとちょっとの手間が大きな時間コストに増大してしまっている部分は体制の問題だとして、 「ちょっとの手間」が増えてるのは事実ですね。 エラーの完全列挙をするときは気をつけないと、 下層でエラーが一種類追加されるだけで、それを呼び出す全ての関数に追加する変更をしないといけない、とかにになって、「大きな手間」になったりもしますね。
t_naruhodo 1
12:27 AM
shizさんのケースは enum のcaseが増えるだけで、エラー型そのものの種類は増えてないので、小さな手間で済みそうですが。
12:28 AM
あと、今列挙する話がここで盛り上がってますが、現在のdorgの実装としては列挙する方針ではなくて単一エラーですね (edited)
12:28 AM
いくつか書き込みに対するレスポンスとして、「それは any Error にするといいね」って回答されてます
Avatar
結局existentialが許されるのか。
Avatar
any Error つまり ただの throws ですね
Avatar
下層でエラーが一種類追加されるだけで、それを呼び出す全ての関数に追加する変更をしないといけない、とかにになって、「大きな手間」になったりもしますね。
多分、さっきの any Error が出てくるとか下層のエラーが型に現れてくるとかから考えても、各レイヤーのセマンティクスで定義されるエラーは下層のエラーを含まない(ラップしない)というのが型的には正しそうな気がする。そうすれば、Existentialは必要ないし、下層のエラーのセマンティクスで上層の利用者がハンドリングしてしまうことがない。 けど、現実的には下層のエラーの理由を知りたいし、ログに残したいし、そういうわけにもいかない。なんか別口でエラーの原因を取得できる口があるといいのかなぁ。
Avatar
Avatar
koher
下層でエラーが一種類追加されるだけで、それを呼び出す全ての関数に追加する変更をしないといけない、とかにになって、「大きな手間」になったりもしますね。
多分、さっきの any Error が出てくるとか下層のエラーが型に現れてくるとかから考えても、各レイヤーのセマンティクスで定義されるエラーは下層のエラーを含まない(ラップしない)というのが型的には正しそうな気がする。そうすれば、Existentialは必要ないし、下層のエラーのセマンティクスで上層の利用者がハンドリングしてしまうことがない。 けど、現実的には下層のエラーの理由を知りたいし、ログに残したいし、そういうわけにもいかない。なんか別口でエラーの原因を取得できる口があるといいのかなぁ。
その取得できる口が enum APICallError { case ... case network(any Error /*これ*/) } ↑に該当するのではないでしょうか? (edited)
t_naruhodo 1
Avatar
enum CallError { case network(underlyingError: URLError) case json(underlyingError: any Error) case authentication } みたいな感じで下層エラーをさらに握っておく形になるでしょうね (edited)
👉 1
t_naruhodo 1
12:32 AM
実質的にエラーがコールスタックみたいになる。
12:33 AM
あんまり詳しくないですがGoのエラーも最近はラップし続けながら上に流して、取り出す側は中のものをフラットに扱いながらダウンキャストする、みたいな感じになってたと思います
Avatar
ObjectiveCでちゃんとエラー返り値(ダブルポインタのやつ)やろうとしたとき、 下のエラーを userInfo.undelyingError で包んでたらコールスタック手作りみたいになってウーンとなったのを思い出した。 (edited)
t_wakaru 1
Avatar
Swiftもだけどスマートにcatchする文法がほしい
Avatar
typed throwsやるなら、同時にuntagged union ( T|U ) の整備も必要だと思うのだけど、そういう指摘はあるかしら (edited)
Avatar
omochimetaru 9/21/2023 1:10 AM
指摘というかトピックとしてはかなり触れられていて
Avatar
現実的にenumで頑張るのは無理筋だと思う
Avatar
omochimetaru 9/21/2023 1:12 AM
1. throws句に複数列挙できるかどうか 2. unionを導入するかどうか の論点があるけど、コアチームの方針は 1については単一で、2は否定されてenum書いてね、に見える。
Avatar
いやー厳しそう
Avatar
omochimetaru 9/21/2023 1:13 AM
そもそもモチベーションとして、組み込み環境のローレベルAPIみたいな、単一enumで列挙可能+existentialのコスト回避したい、というのがターゲットと考えられていて
1:13 AM
アプリケーションに出てくるたくさん並べるやつは今まで通り throwsany Error が良いだろう、
1:13 AM
って話になってるよ
Avatar
TypeScriptでUnionは厳しいと感じてるけど、メタタイプのあるSwiftなら違ったりするのかなぁ
Avatar
まあ不便になるわけじゃないって話か
Avatar
omochimetaru 9/21/2023 1:15 AM
メタタイプがあるかどうかとunionの使い勝手は関係あるかしら
Avatar
メタタイプがあるかというよりは実行時型情報の有無でした
Avatar
omochimetaru 9/21/2023 1:15 AM
あ、それはわかる(実行時型情報)けど疑問点は一緒です (edited)
Avatar
ダウンキャストができないなどです
1:15 AM
(もちろん自前でメタタグをつければできるけど)
Avatar
framework毎に、そのframeworkで発生する全てのエラーを包んだError型を定義してそれを使うのが流行りそうだ。そしたらfunction毎の多重ネストenumになるのはframeworkの毎になって緩和される
Avatar
あと型として複雑すぎてジェネリックに扱う時に苦しい場面が多い
Avatar
omochimetaru 9/21/2023 1:16 AM
classインスタンスだったら実行時ダウンキャストは instanceof でできますね 構造的な型の話?
Avatar
structualな場合ですね (edited)
Avatar
tsでunion辛いは、例えばkindを宣言したりして緩和するけど、それは実行時型情報あれば出来るから
Avatar
omochimetaru 9/21/2023 1:16 AM
ある意味TS環境に関して言えば、クラスインスタンス=メタタイプを持っているオブジェクト と言えると思います。
Avatar
classは基本使わないので。
Avatar
omochimetaru 9/21/2023 1:17 AM
構造的部分型は構造だけに依存するゆえに互換性などが取れるというメリットと表裏一体なので
Avatar
そもそもclassを使えという話になるのかもしれないけど、sealed classがないから型安全になれないですし。
Avatar
tsで辛いのはclass使わずobjectと純粋関数でやるスタイルのせい、はあると思う
Avatar
omochimetaru 9/21/2023 1:17 AM
構造的部分型に実行時型情報を付与する、という話になると矛盾が生じて別の問題が起きそう。
Avatar
同じ辛さはswiftでunionした場合は起きないと思います
Avatar
omochimetaru 9/21/2023 1:18 AM
たとえば構造的部分型は A & B みたいな状態を扱えるし、後で知らなかった C にも準拠できたりします。
Avatar
https://discord.com/channels/291054398077927425/291054454793306112/1154224592618004581 こっちもまあまあ苦しいと思ってて、何かをジェネリックにしたいときにunionが混じってると型が変に分裂したりして1個タプルで囲ったりそもそもわからんくなったりといった場面が多い
Avatar
omochimetaru 9/21/2023 1:19 AM
でもそういうのは実行時型情報にするにはSwiftみたいにコンパイルタイムにconformanceを全部書いておかないといけないはず。
1:19 AM
ランタイムで判定しようとするとプロパティ定義を見ることになって、それは結局メタタイプが無い状態に戻ってます。 (edited)
1:22 AM
TypeScriptに sealed class と new でコンストラクタ呼ばなくても完結にかけるオブジェクトリテラル式によるnewと、クラスオブジェクトに対するオブジェクト展開構文 { ...s } などなど、が、あれば良いんじゃないか・・・?
Avatar
TSで使っててしんどいのは構造的な型で区別つけづらいのと、Conditional typeを含むジェネリックな式で複雑すぎて手がつけられなくなる、という点なので、Swiftなら上手に扱えるのかもという気持ちになってきた
Avatar
omochimetaru 9/21/2023 1:23 AM
あ、でもTypeScriptって、「Aにプロパティxを足した型」みたいな、オブジェクトに対する操作で定義したテンポラリな型が頻出するので、これがクラスというかnominalな道具だと扱えないですね (edited)
Avatar
Avatar
Iceman
https://discord.com/channels/291054398077927425/291054454793306112/1154224592618004581 こっちもまあまあ苦しいと思ってて、何かをジェネリックにしたいときにunionが混じってると型が変に分裂したりして1個タプルで囲ったりそもそもわからんくなったりといった場面が多い
omochimetaru 9/21/2023 1:24 AM
こっちについてはSwiftだったとしても同じになりそう?
Avatar
そもそもswiftだと部分型作ってもconformance無しに使えないから、実行時に型がないって事にはならなさそう
Avatar
omochimetaru 9/21/2023 1:25 AM
つまり部分型を事前に宣言しておかないとダメですね。 (edited)
Avatar
Avatar
omochimetaru
こっちについてはSwiftだったとしても同じになりそう?
each repeatを用意してくれるSwiftなら同様にいい感じにUnionを扱ういい感じの構文を用意してくれれば何とか。
Avatar
Avatar
Iceman
each repeatを用意してくれるSwiftなら同様にいい感じにUnionを扱ういい感じの構文を用意してくれれば何とか。
omochimetaru 9/21/2023 1:28 AM
指摘してる問題が具体的にイメージできてないので文法の問題なのかどうかよくわからないです。
1:28 AM
unionが分裂したり畳み込まれたりする事自体はunionの本質的な性質なので、そのややこしさ自体は取り除けないと思っています。
Avatar
それはそうですね。継承関係が普段と逆向きだったり、分裂したりするのが難しいです。 それだけ複雑で難しい構文であるにもかかわらず、TSは(それ以外にろくな表現力を持たないので)頻出してて難しいなと
1:31 AM
文法が改善されれば理解が容易になるかどうかは僕もわからないです
1:32 AM
eachなどで型が分裂することが明記できてるのはSwiftの良い点だなと。 (edited)
Avatar
omochimetaru 9/21/2023 1:33 AM
分裂と言っているのは↓の事であってます? type AB = A | B // 素直な分裂 type K<X> = N | M | X type KAB = K<AB> // = N | M | A | B // 構造的な分裂 type O<X> = { o: X } type OAB = O<AB> // = { o: A } | { o: B }
Avatar
そうですね。たしかMapped Typeでも扱いが特殊だったはず
1:39 AM
最近難しいと思ったのは interface ReturnNotUndefined { (...args: any): Promise<NonNullable<unknown>> | NonNullable<unknown> } const a = (() => 42) satisfies ReturnNotUndefined; const b = (() => null) satisfies ReturnNotUndefined; // エラーになる、嬉しい const c = (async () => null) satisfies ReturnNotUndefined; // エラーにならない、嬉しくない こういうnon nullなTを返すsyncまたはasync関数を定義したいときに、うまく区別できなかったりとか
1:40 AM
(これはPromise<null>NonNullable<unknown>なせい)
Avatar
omochimetaru 9/21/2023 1:40 AM
ww
Avatar
これはintersection typeの話ですが、 type AAA = string & { foo: null }; type BBB = Omit<AAA, "foo">; function useString(str: string) {} function useBBB(bbb: BBB) { useString(bbb); // Argument of type 'BBB' is not assignable to parameter of type 'string'. } fooをうまく剥がせなかったりとか。
Avatar
omochimetaru 9/21/2023 1:40 AM
これは Promise に包まない場合を許してるのがよくなさそうですが、 TSは (JSは) Promise.then のシグネチャがそもそもそうなってたりして終わってますね (edited)
Avatar
type _CCC<T> = T extends infer U & { foo: null } ? U : never; type CCC = _CCC<AAA>; function useCCC(ccc: CCC) { useString(ccc); } こうやってinferを使えば剥がせますが、逆にConditional Typeに依存することでTがまたunionやintersectionだったりしてUとの間に綺麗な継承関係を作れなかった場合に崩壊したりとか。
Avatar
Avatar
Iceman
これはintersection typeの話ですが、 type AAA = string & { foo: null }; type BBB = Omit<AAA, "foo">; function useString(str: string) {} function useBBB(bbb: BBB) { useString(bbb); // Argument of type 'BBB' is not assignable to parameter of type 'string'. } fooをうまく剥がせなかったりとか。
omochimetaru 9/21/2023 1:42 AM
これはなんでだめなんだ、深淵に踏み込んでそう
1:42 AM
う〜〜ん。
1:43 AM
確かにnominal + unionで簡単になりそうまでは同意なんですが、 一方でunionという概念自体がstructuralなので、 中途半端にunionだけ入れた状態では変な困りが生じそうな気がしますねえ
1:43 AM
メインの型の方もstructuralに行かないと。
Avatar
お疲れ様です。質問させていただきます。 iOSアプリでユーザーセッションをキーチェーンに保存し、ユーザーが別のデバイスに移行し、同じApple IDを使用してアプリをインストールした場合、キーチェーンに保存されたセッションを復元できるかどうかについての質問です。こちらが可能かどうか教えていただければ幸いです。 また、もし可能であれば、以下の3つの関連する点についてもお伺いしたいです。 設定アプリでiCloudキーチェーンの共有をオフにしている場合、セッション情報は他のデバイスと共有されるのかどうか 移行方法によって、セッション情報が共有されない可能性があるかどうか 複数のデバイスでアプリを使用している場合、デバイスごとに異なるセッション情報が生成されず、セッション情報を同期させる仕組みが存在するかどうか
Avatar
同じApple IDでインストールしてるかどうかはアプリ側で判断する術がないはずなので、キーチェーンに保存したものはiCloudキーチェーンで共有されてないと、その情報は別の端末で読み取れないはずです 🤔 セッション情報の完全同期も基本難しい(オフライン時に同時に作られたものが複数ある時、オンラインになった時どれを取るかみたいな問題)ので、Safariのタブみたいに、端末ごとのセッションを持ってそれらを全部iCloudとかで上げるのが一番無難かなと思います
Avatar
Kishikawa Katsumi 9/21/2023 6:30 AM
Keychainの属性にThisDeviceOnlyを設定してなければ別のデバイスにデータを移行(復元)するとKeychainも移行されるのでそういうシナリオもあります。
Avatar
ありがとうございます。 今回のケースはアプリ内での処理で簡単にできる方法を模索しておりましたので、同期の仕組みを提供する方法は採用せずとしたいと思います。 Keychainの属性にThisDeviceOnlyを設定せず、iPhone→iPhoneによるデバイス移行の手順を踏んだ場合に同期ではなく、移行されるという流れですね。 こちらの事情を色々お伝えしておらずでしたが、現実的な落とし所なような気がします。 お二人ともありがとうございます!!
🙌 1
Avatar
typed throwsやるなら、同時にuntagged union ( T|U ) の整備も必要だと思うのだけど、そういう指摘はあるかしら
typed throwsと別のスレッドができましたね。(Coreチーム発ではないですが) https://forums.swift.org/t/structural-sum-types-used-to-be-anonymous-union-types/67432
(edited)
Spinning off a new discussion thread on the topic of anonymous union types from the Status check: Typed throws thread. The spin-off discussion on this topic began somewhere around this comment.
👀 1
Avatar
Hi everyone. The review of SE-0410: Atomics begins now and runs through November 6th, 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 contacting the review m...
1:08 AM
Swift標準ライブラリにアトミック操作ライブラリ(型)を追加する提案
1:11 AM
ついに言語標準に追加されることになったので、
1:11 AM
メモリオーダーについて勉強しなおした
1:14 AM
前のエントリで次期C++標準(通称C++0x)にatomic型とメモリバリアが導入されるという話をしました。今回はそのC++での実装について、もう少し深く追いかけてみます。 スライド資料では「atomic操作 + acquire/releaseバリア」が基本であると書きましたが、実際に次期C++に導入される予定のatomic APIは、もう少し複雑な仕様になっています。一番の違いは、メモリバリアの種類が増えていることです。 次期C++標準の現在のドラフトでは、メモリバリアの種類を表すenum型の定義は以下のようになっています。 namespace std { typedef enum memo…
👀 1
1:15 AM
この記事がわかりやすかった
1:15 AM
seq-cstレベルを指定しなければバグる例を見ると
1:16 AM
もはや現代のコンピュータは、「一つのメモリ空間を複数のスレッドが順番に操作する」という解釈では説明できない挙動をすることがわかる
1:17 AM
まるで、スレッドごとにパラレルワールドが見えていて、それぞれで異なる順番で事象が起きたような挙動をする (edited)
1:22 AM
マルチスレッドプログラムの挙動の正しさを考える時、素朴に「もしこの時系列で各スレッドが動作したら・・・」というふうに考えているけど、それだとバグの事前の発見という意味では、十分ではないんですねえ
Avatar
swift-atomicsとの違いは何なんでしょうね
Avatar
プロポーザルを読む限りでは
Avatar
ちょっと言及があった。基本は同じ機能を提供するけど、経験を活かしてちょっと良くしてるらしい
Avatar
そうですね、APIとしてはそう
1:34 AM
それと、システムプログラミング言語になるためにはSwift標準ライブラリに必要、というのと、pure swift実装という事が言及されてる
1:35 AM
swift-atomicsはコアな部分をC言語で実装している+外部パッケージだから
1:36 AM
組み込みなどの特殊なプラットフォームではそれがめんどくさい状況を引き起こしうる?のかも。 (edited)
1:36 AM
あと、
the swift-atomics package was shortly created to experiment and design what a standard atomic API would look like
によると
1:38 AM
swift-atomicsは、標準APIの設計をどうするか実験するために作られたパッケージ、だったらしい?
1:38 AM
swift-atomicsによって経験を経ていい感じのAPIが十分わかったのでいよいよ標準ライブラリに導入するぞ、という事でもあるのかも
Avatar
そういえばなにかがリンクできなくて困ったケースありましたね
Avatar
それはあれですね
1:48 AM
scipioによるカスタムビルド (edited)
Avatar
Low-level atomic operations for Swift. Contribute to apple/swift-atomics development by creating an account on GitHub.
1:48 AM
このへんのやつ
Avatar
そうそう、Swiftランタイム関数をリンクしようとしているけど
1:48 AM
C側から適切?にその依存を表明できていないから
1:49 AM
リンカーに libSwiftCore が渡されないからビルドできない
1:49 AM
dynamic libraryだとCAtomicsを単体でビルドしようとするからそうなってしまう
1:49 AM
static libraryだと、リンクは最後まで遅延されて、そのときにlibSwiftCoreが巻き込まれるから大丈夫
1:49 AM
今は、そのリンク先のように asm命令でリンカーオプションを埋め込む魔術によって、どうやらなおったらしい。 (edited)
1:50 AM
本質的には(さまざまなものが完璧なら)問題ないはずだけど、実用的には(変な罠やバグをふんだりするから) swift package + Cコード混在である事で、面倒な状況はあるってことですよね (edited)
Avatar
<stdatomic.h>使ってそうですもんね
1:51 AM
それがSwiftのBuiltinに依存するようになったから、問題が起きにくくなりそう
Avatar
#if !defined(ATOMICS_NATIVE_BUILTINS) && defined(__swift__) && !defined(__cplusplus) # include <stdatomic.h>
1:52 AM
ほんとだ。
1:52 AM
C言語じゃなくてC++言語ビルドじゃないと動かないのかなあ?
Avatar
Hello Swift community, I'm pleased to announce that the Language Steering Group has accepted a vision document for Embedded Swift: This document presents a vision for "Embedded Swift", a new compilation model of Swift that can produce extremely small binaries without external dependencies, suitable for restricted environments including embedd...
12:29 AM
Embedded SwiftのVision DocumentがAcceptされてた
12:32 AM
embedded modeでダイナミックな型の機能が全部禁止されて、non allocating modeでヒープメモリ確保するものが全部禁止される
12:33 AM
前者についてはバイナリサイズ削減を重視しているので部分的に使えるならWASM用途にも良さそう
Avatar
Kishikawa Katsumi 11/1/2023 12:41 AM
組み込み系でSwiftが覇権を取ったらおもしろいな。
Avatar
Swift目線だと制約キツいけど、組み込み系なら普通の制約だから、その元でCやRustと比較されそう でも組み込みエアプだからどんな評価になるかイメージ付かないなー
Avatar
キツキツ制約の下だと単にRustの劣化になってしまわないかが心配だ (edited)
Avatar
Kishikawa Katsumi 11/1/2023 2:35 AM
Pythonもけっこう使われてるのかな。競争相手多いな。
Avatar
Kishikawa Katsumi 11/1/2023 8:18 AM
2年ほど前からInfo.plistってバイナリに直接埋め込めるようになってたんですね。 https://www.polpiella.dev/info-plist-swift-cli/
Find out how to add extra information to your Swift command-line tool through an Info.plist file while keeping it as a single-file executable.
Avatar
omochimetaru 11/1/2023 8:45 AM
へー、専用のセクションとして入れたらいいんですね
Avatar
Hello everyone, We'd like to share a proposal that've been working towards for a while now. Read the full proposal here: SE-NNNN: Task Executor Preference. (In case of small typos, please comment on the pull request) The proposal introduces task executors which enable a structured task hierarchy to have a "preference" where all of its tasks...
👍🏻 1
11:36 PM
konladさんが下書きしてたやつフォーラムに投稿された
11:36 PM
Actorに紐づかないTaskのexecutorを指定できる仕組み
11:37 PM
これでswiftnioのEventLoop threadでTaskが実行できるので、nioをswift concurrencyと組み合わせた時の無駄なホップが無くせる (edited)
Avatar
Embedded Swiftというのが議論されているのですね。IOKitがEmbedded C++なので、代替になれば面白いですね。
Avatar
omochimetaru 11/2/2023 1:57 AM
IOKitがEmbedded C++
おお〜そうなんですね
Avatar
C++ですが、NeXTSTEPのDriverKitの流れなのか、クラスの仕様がObjective-Cとなっています。 例えば、クラスの初期化がコンストラクタでなくinitで行うとか。
2:16 AM
ほ、ほんとだ、なんだこれわ
Avatar
Swiftをそのまま組み込みで使うのかC++ interop経由でやるのかどっちがいいか難しそうですね。
4:15 AM
どこまでを組み込みとするか怪しいですが、Linux版Swiftをテコ入れするのでも良さそうな気がする...
Avatar
組み込み環境はSDKなどがC/C++なので、最初はinteropが良いけど、だんだんそれをラップしてSwiftライブラリを揃えていく進み方をすると思います。 Linux向けSwiftは普通にデスクトップ想定で、メモリ量なども潤沢なので、Embedded Swiftでターゲットにしてる環境ではないと思います。 自作キーボードだと現代でもマイコン環境が割と普及してるのでターゲットになりそう。
Avatar
Raspberry Pi PicoとmicroPythonで自作キーボードみたいな話も見ますよね。 microPythonがやっぱり競合になるんだろうか…?
Avatar
Kishikawa Katsumi 11/12/2023 7:42 AM
microPythonはたぶん競合になると思いますねえ。
7:43 AM
Raspberry Pi Picoもそうだし、ESP32でもSwift使えたらよさそう。
Avatar
A follow-on to SE-0380. Keen to hear everyone's thoughts on the alternatives outlined at the end. Available as a PR here. Multi-statement expressions using then Authors: Ben Cohen, Hamish Knight Review Manager: TBD Status: Awaiting Implementation Implementation: available on main via -enable-experimental-feature ThenStatements and -enable-expe...
6:10 AM
then文のピッチ
6:10 AM
だいたい事前リークどおり ついでにdo式も誕生するよ
Avatar
do式ちょっと欲しかった奴っぽい
6:11 AM
tryをシュッとguardに押し込むみたいなことが出来るようになりそう
👉 1
Avatar
使い捨てクロージャ書く系のパターンが言語サポートされるとreturnでの帯域脱出もできるし、記号もちょっと減るし嬉しいね
Avatar
if式入ったタイミングでthenも入ってると思ってたら入ってなくてつかえね〜ってなってた
Avatar
一行制限結構渋いよね
Avatar
これで三項演算子と差別化できる
Avatar
あ、たしかに。そういう見方もあるのか。
Avatar
これってバグだと思うんですけどどうでしょう? たとえ var があったとしても、main actor isolate されていたら、 外からのアクセスも、自身からのアクセスも、 main actor context からのアクセスではない場合は await が必要になるのだから、安全であり、 Sendableでいられると思う・・・ 実際、 このような var って func b のようなメソッドによるgetterとsetterのようなものだと思うので。 (edited)
Avatar
global
1:40 PM
actorついてない場合に安全じゃないのは正しいと思いますが、その警告がglobal actorついてても出てきてるのは変そうですね
Avatar
ですよねえ
Avatar
あー、inoutで渡せちゃうから?
1:42 PM
いや渡すところで禁止されますよね
Avatar
inoutはget and setですよ
1:43 PM
あーでもasyncにできないか
Avatar
Function Body Macroの提案仕様が更新されたようです。 投稿 https://forums.swift.org/t/function-body-macros/66471/59 プロポーザルドラフト https://github.com/apple/swift-evolution/pull/2219/files (edited)
👀 1
12:36 AM
肝心の問題である関数本体を書き換えるマクロの型チェックについてですが
12:37 AM
preamble: 先頭に追記するだけ、型チェックはマクロ展開前の状態で行う body: マクロ展開前は構文チェックだけ行う、型チェックはマクロ展開後の状態で行う という方針のようです
12:39 AM
The function body as written must be syntactically well-formed (i.e., it must conform to the Swift grammar) but will not be type-checked, so it need not be semantically well-formed.
Avatar
フォーマルな言語仕様としての話で、IDEが推論に基づく支援をするのは別に禁止はしないんだろうな。
Avatar
すいません、Swiftについてでなく、Xcodeに関してなのですが・・・。 macOS Sonoma 14.1.2 に、Xcode14.3.1 をインストールしたいのですが、どうしたら良いでしょうか。 Xcode14.3.1 のダウンロードは出来ましたが、インストールができません、エラーになってしまいました。
Avatar
omochimetaru 12/4/2023 3:08 AM
新しいOSと古いXcodeの組み合わせがダメになってる時はどうしようもないです。 (たまに裏技があったりしますが) 代わりにXcode15 をインストールすれば良いです。
Avatar
https://discord.com/channels/291054398077927425/1166660538533679244 ここで上がりましたが、裏ワザがあります
Avatar
よろしければ、裏ワザを、お教えいただけないでしょうか。 Xcode15は、インストールしてあります。Xcode14と、共存させて、切替ながら使いたいのですが・・・。 お手数をお掛けします、何卒よろしくお願い申し上げます。
Avatar
スレッドに書いてありますが、直接起動することが出来ます。またinfo.plistの内容を書き換えても動きます。Xcode14 sonoma infoplist あたりでググれば参考になるものが見つかると思います
Avatar
Avatar
k
よろしければ、裏ワザを、お教えいただけないでしょうか。 Xcode15は、インストールしてあります。Xcode14と、共存させて、切替ながら使いたいのですが・・・。 お手数をお掛けします、何卒よろしくお願い申し上げます。
omochimetaru 12/4/2023 4:33 AM
この吹き出しのアイコンがついた青い背景の文章をクリックすると、Discordの別の書き込みにジャンプできて、そのジャンプ先の書き込みに、裏技のやり方が書いてあるブログ記事へのリンクが、書いてあります。
Avatar
tarunon様 早速のご回答、ありがとうございます。 「 Xcode14 sonoma infoplist 」でググってみます。 感謝いたします。
Avatar
omochimetaru 様 すいません、アイコンがついた青い背景の文章をクリックしても、ジャンプしません。 Discordアプリにて、画面を開いているのですが、ブラウザの方が良いのでしょうか。
👀 2
Avatar
https://discord.com/channels/291054398077927425/1166660538533679244 こちらのリンクだとどうでしょうか?同じかな
Avatar
tarunon 様 ありがとうございます。 クリックしたら、ジャンプしました。 度々のご指導、深く感謝いたします。
Avatar
Avatar
k
omochimetaru 様 すいません、アイコンがついた青い背景の文章をクリックしても、ジャンプしません。 Discordアプリにて、画面を開いているのですが、ブラウザの方が良いのでしょうか。
omochimetaru 12/4/2023 5:55 AM
僕の書き込みの中にあるtarunonの書き込みは、テキストではなく、Discordの画面のスクリーンショット画像なので、クリックできません。
Avatar
連絡が遅れて、申し訳ございません。粗忽者なので、お許しいただけると幸いです。
🙂 1
Avatar
度々、申し訳ございません。 Xcode14.3.1の解凍は、Info.plistファイルとversin.plistのCFBundleVersionにて21815から22265に変更することで、解決しました。 ご指導、色々と、ありがとうございました。 その後、Xcode14.3.1を、アプリケーションディレクトリに移行させて、クリックしましたら、以下のメッセージが出ました。 select the platforms you would like to develop for required additional required components will also be installed macOS13.3とiOS16.4の、インストールを求められました。 どう、対応したら良いか、ご教授いただけると幸いです。 お手数をお掛けします、何卒よろしくお願いします。
Avatar
多分よくあるシミュレーターとかの環境だけかなと思いますので、そのままインストールクリックすればいいはず…?(スクショあるとわかりやすいです)
Avatar
すいません、お手数をおかけします。 画像を、アップします。 もしかして、Info.plistファイルの、DTPlatformVersionとDTSDKnaameを、13.3から14.1.2に変更すれば、良いのかなと考えました。 しかし、他の箇所も変更しなくてはいけないかもしれないのと、予期せぬトラブルの可能性があるかも、と考えて止めました。
Avatar
これは普通に必要なので要求されてますね。installして良いと思います。
8:30 AM
質問ですが、 #beginner-help-archived #beginner-help というスレッドも用意してるので、そちらの利用もご検討ください
Avatar
ありがとうございました。 Xcode14.3.1のインストーと起動が、出来ました。 深く、感謝申し上げます。 「beginner-helpとbeginner-help-otameshi利用」の件、かしこまりました。 度々の、ご指導、心より御礼申し上げます。
🎉 2
Avatar
Kishikawa Katsumi 12/9/2023 12:08 AM
https://github.com/apple/swift/pull/69457 マクロがProperty Wrappersみたいにモジュール名で修飾できるようになったらしい。 @Observation.Observable final class Dog {} (edited)
Allow attached macro expansion syntax to have a module qualifier, @Foo.Bar. Resolves #65485 / rdar://108621205
👏 9
👀 1
Avatar
お。これは絶対あったほうがいいっすね。
Avatar
async deferは書けないですよね?awaitする処理をdeferに入れたかった。
Avatar
書けないです!
Avatar
ありがとうございます。諦めます!
Avatar
自前でスコープ関数定義するとかしかないんですよね〜
Avatar
Kishikawa Katsumi 12/20/2023 9:50 AM
https://forums.swift.org/t/embedded-swift-running-on-the-raspberry-pi-pico/69001/5 RP2040でSwiftが動くらしい。今はまだC++のSDKをSwiftから使ってるだけだけどSDK自体もSwiftで書いてみようって話が載ってる。
This is fantastic work, thank you for sharing it on GitHub! This should be possible with Swift SDKs. The build system used for SDK components has no impact on whether you can build software with those components using SwiftPM or not. You only have to assemble an artifact bundle in a format that SwiftPM can understand. Yes, I would love this ...
👀 2
🙌 1
Avatar
RP2040周辺回路がおおくてちょっと使うのが大変
2:11 PM
特にフラッシュ載ってないのがなあ...
Avatar
Kishikawa Katsumi 12/21/2023 10:09 PM
RP2040ならキーボードのファームウェアをSwiftで書けるとよかったりしないかしら。 (edited)
Avatar
フラッシュ乗ってないの地味にだるいですよね
Avatar
なんですよねー
11:33 PM
AtmelがCOVIDで供給不足になってありえん高さ&リードタイムになったときに安定供給されたrp2040は魅力があったのですが、
11:33 PM
周辺部品の多さ、3v3つくらなきゃいけないとかでかなり気合いがいるチップなのは事実です
11:34 PM
ただ、仕様や挙動がとてもSWE向けでかつそういう理由で設計の自由度があるので(e.g. flashのサイズが自在)、おおきなソフトウェアも載せられたりして
11:35 PM
十分有望な選択肢だなとは思ってます
11:36 PM
ただキーボード如きには過剰かもと思ったり。
11:36 PM
話かわりますが... (edited)
11:37 PM
@Observableと@MainActor使うとactor isolationが怪しくなる問題があって
👀 1
11:37 PM
macroの実装知りたいと思ってるんですが、良い方法なんかないですかね... (edited)
Avatar
Observableマクロの実装ですか?
Avatar
ですね...
12:35 AM
SILみるとだいぶいろいろなことをしてくるようで...
Avatar
まず、一番簡単な初手は、Xcodeで右クリックして expand macro
12:56 AM
その次は、リポジトリにあるテストケースを見ることだと思います。 展開前と展開後のコードとして書いてあるので
12:56 AM
で、さらにその次は、ObservableMacroの実装を直接読むことだと思います。
Avatar
ObservableMacroの実装って公開されているんですね。(勝手に非公開だと思いこんでいた) https://github.com/apple/swift/blob/main/lib/Macros/Sources/ObservationMacros/ObservableMacro.swift
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
😲 1
t_sorena 1
Avatar
なんと、公開されてるのか...
1:01 AM
ソースない前提だった
Avatar
ObservabilityはSwift ProjectでFoundationみたいなApple Projectじゃないので
1:02 AM
普通に全部見えますよ。
Avatar
勝手にAppleがこっそり作ってるSwiftUIみたいなやつだと思ってた。思い込み。
t_wakaru 2
Avatar
なるほど、そこか
Avatar
ドキュメントに(あるものは)ソースコードへのリンクつけて欲しいですねー。 (edited)
Avatar
omochimetaru 1/5/2024 6:48 PM
Hello, Swift evolution! I wrote up a dedicated pitch detailing solutions to two fundamental issues with AsyncSequence and AsyncIteratorProtocol: the bespoke-and-limited @rethrows attribute, and issues with Sendable checking when iterating over an AsyncSequence. This includes the typed throws adoption in AsyncSequence and AsyncIteratorProtocol d...
6:48 PM
AsyncSequenceにprimary associated typeつく
6:49 PM
そしてFailureがtyped throwsに渡される
6:50 PM
謎の言語機能 '@rethrows’ はこれで消せるらしい
6:50 PM
それと、non Sendableな値をAsync Sequenceで扱えなかった(スレッド安全が壊れていた?)問題を修正するために (edited)
6:51 PM
新しいnextElementメソッドは引数でoptionalなisolated引数を持つ
6:53 PM
で、for await inの構文展開ではその引数も自動で展開される
6:55 PM
たしかこれまでのisolatedはActorを取らなきゃいけなくて、nonisolatedを示す方法がなかった この言語仕様が緩和される
Avatar
omochimetaru 1/6/2024 5:13 AM
これまでのnextは互換性のために残ってこれからはnextElementを使うらしいけど、苦しいな
5:16 AM
nonisolatedをnilにするためにsome Actor?にできなくてany Actor?になるのもモヤッとするね
5:17 AM
optionalな引数でよくありそうだ
Avatar
むむ?確かに型が確定しないからsomeになれないんですね
8:51 AM
そのとき(nil相当の挙動をさせたいとき)はnextでいい気がするけど、そうはいかないんでしょうかね (edited)
Avatar
omochimetaru 1/6/2024 10:11 AM
代案のところに書いてあるけど、メソッドを別にするアプローチは実装共通化できなくて微妙だそう
10:12 AM
今のアイソレーションを取得する #isolation の話もありそれも意識してそう
10:13 AM
nonisolatedもisolationの一種として、値として扱えるようにgeneralizeしたいそう
Avatar
ここに書かれていた新しいavailabilityチェックのところがよくわからなかったのですが、Swift5.11からはnext()nextElement()のどちらかは実装しなければならなくなるので、Swift5.11以前から使っていたものも実装が追加に必要になるということですか? あ、そもそも今はデフォルト実装がないからnext()は必ず実装されているのか。 ``` To avoid silently allowing conformances that implement neither requirement, and to facilitate the transition of conformances from next() to nextElement(), we add a new availability rule where the witness checker diagnoses a protocol conformance that uses an deprecated, obsoleted, or unavailable default witness implementation. Deprecated implementations will produce a warning, while obsoleted and unavailable implementations will produce an error. (edited)
Avatar
omochimetaru 1/6/2024 10:27 PM
そこの話は、互換性のためのデフォルト実装と、これからのためのデフォルト実装で、どっちのメソッドももう片方を使ってデフォルト実装されるから
10:27 PM
そのままだとどっちも実装しないままでOKになって実行時に壊れてしまうので
10:28 PM
nextElementは手で実装しないと(デフォルト実装はあるけど)怒られるようにする、ということだと思った
Avatar
特に既存の実装を変更しなければならないという訳ではないんですね。 ありがとうございます!
Avatar
omochimetaru 1/7/2024 2:42 AM
そうですね。 ただし新しいSDKだとnextElementを実装するように警告が出るかと
t_naruhodo 1
👍🏻 1
Avatar
omochimetaru 1/30/2024 7:24 AM
Hello Swift community, The review of SE-0421: Generalize effect polymorphism for AsyncSequence and AsyncIteratorProtocol begins now and runs through February 7, 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, direc...
7:24 AM
新しいAPIが next(isolation:) になったおかげで next() とオーバーロードできるようになって、シンプルな next という名前を維持できる結果になってる。 (edited)
👏 5
Avatar
omochimetaru 2/8/2024 5:04 PM
Hi all, I would like to propose a new type in the Synchronization module, Mutex. This type is a synchronous mutual exclusion lock, similar to things like OSAllocatedUnfairLock, NIOLock, etc. Please let me know what you think! Synchronous Mutual Exclusion Lock 🔒 Proposal: SE-NNNN Author: Alejandro Alonso Review Manager: TBD Status: [stdlib] Imp...
5:05 PM
SynchronizationモジュールにMutexを追加する提案 いわゆるロック
5:06 PM
GCDでDispatchQueue使いましょうからの、Actorで、ロックを提供しない長い歴史を経て、結局提供するんかい、と思った
5:07 PM
まあ、結局ローレベル実装では必要だからstdlibやらswift-nioで再実装しまくってるのは良くないね、というのはシンプルによくわかるけど。
Avatar
こういうクロスプラットフォームなプリミティブが無いとシステムプログラミング言語として闘っていけない!
Avatar
omochimetaru 2/8/2024 5:15 PM
間違いない
Avatar
真面目な話として使いやすいロックが無いと、何も保護せずとりあえず @unchecked Sendable をつけるコードが蔓延していく未来が。
Avatar
omochimetaru 2/8/2024 5:24 PM
今だと DispatchQueueを隣に作ってgetterとsetterをDispatchQueue.syncで保護するのが標準的で移植性も高い書き方という認識
5:26 PM
キューの名前を要求されるのと隣に置くことになるから変数名がもう一個必要で、まあめんどいのはわかる
Avatar
なるほどそれは現状だとかなりポータブルで少ない手数で書けていいな
5:27 PM
まあ1つのストレージ保護するためだけだとDispatchQueue持ち出すのは仰々しい気もしますが
Avatar
omochimetaru 2/8/2024 5:28 PM
内部的には結局DispatchQueueを実装するためのミューテックスが一個生成されてるだけな気はしてる(asyncしてないならスレッドは確保されない)
5:28 PM
意味的にはオーバーキルなのはそう
5:29 PM
Mutex<Foo>で楽になるのは良いですね
5:29 PM
逆に今更やるならもっと早い時からあって良かったじゃん感あってモヤモヤする (edited)
Avatar
~Copyableが必要なんですよ!
Avatar
omochimetaru 2/8/2024 5:31 PM
あー
5:31 PM
間接化しないでそこに置きたいからstructにしたいけどコピーされてぶっ壊れるのも嫌なのね
Avatar
そうそう
Avatar
omochimetaru 2/8/2024 5:32 PM
最高の形で導入するためにずっと力を溜めてたのか・・・
Avatar
時は満ちた
Avatar
omochimetaru 2/8/2024 5:34 PM
distributed actorみたいなめっちゃハイレベルな機能とか作った後で、non copy入れてシステムレベルプリミティブに戻ってくる開発計画なんなんだ (edited)
5:35 PM
普通に考えるとローレベル周りからじっくり積み上げていったほうが変な破綻が起きにくそうなのに。
Avatar
どうなんだろう、真のローレベルであるところのCとのinteropは最初から提供してたからSynchronizationモジュールみたいなやつはローレベルな機能を提供するのが目的というより、ミドルレベルというか使いやすさのためにギャップを埋めるもののように感じてきた
5:41 PM
なので実は上下から攻めていたのではないか
Avatar
omochimetaru 2/8/2024 5:42 PM
なるほど・・・ 確かにc interopで誤魔化せるものをお行儀よく使うものだから、できないことをできるようにするよりは後回しなのは自然なのか
Avatar
ConcurrencyとかDistributed ActorとかはCでは逆立ちしても難しい…
Avatar
omochimetaru 2/8/2024 5:45 PM
そうだねえ asyncの前って何やってたっけ property wrapperとかORTだっけ
Avatar
そのあたりのSwiftUI向けのやつだったかなぁ
5:48 PM
あーあとStable ABIか
Avatar
omochimetaru 2/8/2024 5:49 PM
ABIたしかに
Avatar
歴史だ...
Avatar
Swift5.0(2019-03-25)がリリースされてからもう5年経とうとしているんですね…(こわ) https://github.com/apple/swift/blob/main/CHANGELOG.md#swift-50
Avatar
omochimetaru 2/9/2024 2:00 AM
Swift5系、長生きですね。
Avatar
Swift、とても好みな言語なのでさまざまなプラットフォームでどんどん使える様になって欲しい...特に組み込み...
Avatar
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
12:35 PM
GSoC2024のテーマおもしろい
12:36 PM
・SwiftSyntaxにAST解析を入れる 順当にcxxからswiftにコンパイラ実装を引っ越すための次のステップ
12:38 PM
・AsyncHTTPClientにtracingサポートを実装 今業務でトレーシング入れてるんだけど、AHCがネイティブサポートしてくれないと困るなーとちょうど思ってた (edited)
12:40 PM
・プロパティラッパー実装をコンパイラから剥がしてマクロ化する これも良いよね、プロパティラッパー関係は型推論とかにも特別実装入ったりしてて大変
Avatar
GSoCおすすめです
Avatar
omochimetaru 2/12/2024 1:00 PM
家庭くんのバイナリサイズ減らすやつってそういえばどうなったん
Avatar
大体のDCEはhermetic-seal-at-linkによるLLVMレベルのLTOで達成できたのであとはSwiftPMとのインテグレーションですね
Avatar
プロパティラッパーをマクロ化はそもそもできるんでしょうかね?
1:06 PM
仕様的に無理なパターンがあったような?
1:09 PM
_enclosingSelf含めて行けるような気もしてきた
Avatar
Avatar
Yuta Saito
大体のDCEはhermetic-seal-at-linkによるLLVMレベルのLTOで達成できたのであとはSwiftPMとのインテグレーションですね
omochimetaru 2/12/2024 1:10 PM
あ、そうなのか。じゃあブロッカーは特に無いけど進んでないのは強いモチベーションが無いからか・・・? 実際順番的にはWASMとかembeddedサポートが公式に確立してからな気もする 「LLVMレベルのLTO」は家庭くんの発表に出てきた、継承関係とか考慮してメタデータも消すやつ、は含まない?
Avatar
Avatar
Iceman
仕様的に無理なパターンがあったような?
omochimetaru 2/12/2024 1:11 PM
Macros and init accessors in their current state might not be sufficient to cover all of the property wrapper uses scenarios, so the project is most likely going to require improving and expanding aforementioned features as well.
仕様的に無理な場合みたいなケースを洗い出してマクロ側の仕様を強化するとかの作業も見据えてそう
(edited)
Avatar
Avatar
omochimetaru
あ、そうなのか。じゃあブロッカーは特に無いけど進んでないのは強いモチベーションが無いからか・・・? 実際順番的にはWASMとかembeddedサポートが公式に確立してからな気もする 「LLVMレベルのLTO」は家庭くんの発表に出てきた、継承関係とか考慮してメタデータも消すやつ、は含まない?
Swift SDKの準備とかスレッド対応とか色々先にやらないといけないことが沢山あって優先度低めですねー。
LLVMレベルLTO
hermetic-sealモードでは継承関係考慮するやつが有効になります
Avatar
Avatar
Yuta Saito
Swift SDKの準備とかスレッド対応とか色々先にやらないといけないことが沢山あって優先度低めですねー。
LLVMレベルLTO
hermetic-sealモードでは継承関係考慮するやつが有効になります
omochimetaru 2/12/2024 1:15 PM
なるほど。そういえばずっと前に、build-script なんとかしないとってテーマもあって、その時はこっそりM1チップ対応してるのかな、みたいな話もあったけど、Swift SDKもビルドなんとかしたいやつの一部か
Avatar
Avatar
Yuta Saito
Swift SDKの準備とかスレッド対応とか色々先にやらないといけないことが沢山あって優先度低めですねー。
LLVMレベルLTO
hermetic-sealモードでは継承関係考慮するやつが有効になります
omochimetaru 2/12/2024 1:16 PM
hermetic-sealモードそれも対応してるのか いいねえ
Avatar
Avatar
Yuta Saito
Swift SDKはこれっすね https://github.com/apple/swift-sdk-generator/
omochimetaru 2/12/2024 1:16 PM
ああうん、把握してる
Avatar
ああ、ビルド関連って話でしたか
Avatar
omochimetaru 2/12/2024 1:18 PM
長い目で見れば繋がってるなあと思った
Avatar
ビルドシステムはどこもむずかしくて難しい
Avatar
omochimetaru 2/12/2024 1:18 PM
メタメタしくてややこしいね
Avatar
難しいから時間がかかる…
Avatar
@Foo var value みたいな、型を省略するパターンが難しそう
Avatar
omochimetaru 2/13/2024 1:35 AM
確かに・・・ マクロ展開された computed property は型を明記しないといけないから。 (edited)
1:35 AM
推論された value の型が取れないとどうしようもなさそうですね
1:36 AM
まあせっかくだからマクロに型渡ってくるやつ欲しいですよね
1:37 AM
Code Completion for Keywords using swift-syntax
テーマが増えてる。
Avatar
GSoCに新しい面白テーマ増えました: Building Swift Macros with WebAssembly https://www.swift.org/gsoc2024/#building-swift-macros-with-webassembly (edited)
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
omochimetaru 2/25/2024 4:15 AM
どゆこと!?読むか
4:16 AM
マクロのビルド時間を短縮するためにプレビルドにしつつ、ポータビリティとサンドボックスを担保するのか・・・
4:17 AM
マクロのビルドって一回やるだけだから、そこって問題だったんだっけ
Avatar
一回って言ったってCIとかでは毎回ビルドするんでバカにならないんですよね
Avatar
omochimetaru 2/25/2024 4:18 AM
でもAppleからwasm swiftの話いきなりでてきたのは流れ変わったな
Avatar
Avatar
Yuta Saito
一回って言ったってCIとかでは毎回ビルドするんでバカにならないんですよね
omochimetaru 2/25/2024 4:18 AM
たしかに!
4:19 AM
needleはマクロじゃなくてビルドプラグインだけど、swiftsyntaxのバージョン解決がプロジェクトで混ざる問題があってめんどくさくてプレビルドしたい、とかはあったな
4:20 AM
マクロだけじゃなくてビルドプラグインもwasmにしよう (edited)
Avatar
夢が広がる😁
Avatar
omochimetaru 2/25/2024 4:26 AM
サンドボックスって今はmacosだけなんだっけ
Avatar
そすね
Avatar
omochimetaru 2/25/2024 4:26 AM
そのへんOSごとに対応するのめんどくさそうだから、まるっといけそうでいいね
4:27 AM
mac以外でSwiftのホスト環境使う人いるのか?は謎だけど
Avatar
omochimetaru 2/28/2024 1:00 AM
Hello, Swift evolution! I wrote up a pitch for extending region isolation to enable explicit transferring annotations on parameter and result types to indicate that argument and result values must be in a disconnected region at the function boundary. This enables controlling which parameter and result values are in a disconnected isolation regi...
1:00 AM
transferring 指定子を追加するらしい。
1:01 AM
てっきり演算子の話になると思ったら型のmodifierだったので、直感したものと違う気がする。よく読んでみる。
Avatar
よくみんなが自前でつくるUnsafeTransferのmodifier版?
Avatar
omochimetaru 2/28/2024 1:25 AM
transferring引数: Actorのinitの引数のように、渡された引数がその関数のリージョンに引き渡されるようになる。
1:27 AM
let ns = await withCheckedContinuation { continuation in Task { @MainActor in let ns = NonSendable() continuation.resume(returning: ns) } } Region based isolationの元でこれはエラーになるらしい。 ns が MainActor に居るので resume に渡せなくなる。 (edited)
1:28 AM
public struct CheckedContinuation<T, E: Error>: Sendable { public func resume(returning value: transferring T) } こうすることで、渡せるようになる。 ただし、渡した後ろでは使えなくなる。
1:29 AM
transferring返り値: 呼び出し側から見て、その値がリージョンから引き剥がされている扱いになる。関数自体の実装の正当性はチェックされる。 @MainActor struct S { let ns: NonSendable func getNonSendable() -> transferring NonSendable { return NonSendable() } } nonisolated func f(s: S) async { let ns = s.getNonSendable() // okay; 'ns' is in a disconnected region } (edited)
1:30 AM
↑これはtransferring指定がないと、sのMainActor regionから、let nsに渡せない。
1:34 AM
region based isolationが前提の元で、その挙動を調整するための機能って感じかなあ
1:34 AM
snapshot版じゃないと試せなそうだ
Avatar
なるほど。region based isolationをそもそも使ってなくて馴染みがなかった。
Avatar
omochimetaru 2/28/2024 1:38 AM
うーん。motivation sectionのサンプルをそのままやっても怒られないから課題設定がよくわからん。 https://discord.com/channels/291054398077927425/430242233468452865/1212211519501107300
Avatar
すいませんXでも書いたんですけど、Region based IsolationのFuture directionになんかあったなーくらいな認識しかまだしてなかったので、後でPRちゃんと読んでみますmm ざっくりと異なる分離領域で使われなくするために必要としかまだ理解できていないです。なんとなくconsumingみたいな感じなのかと。。。 actor Actor { func method(_ x: transferring NonSendable, _ y : NonSendable, _ z : NonSendable) async { // Regions: [(x), {(y, z), self}] // Safe to transfer x since x is marked as transferring. await transferToMainActor(x) } } actor Actor { func transfer<T>(_ t: transferring T) async {} func method() async { let a = NonSendable() // Pass a into transfer. Even though we are in the same // isolation domain as transfer... await transfer(a) // Since we transferred a, we are no longer allowed to use a here. Error! useValue(a) } } https://github.com/apple/swift-evolution/blob/main/proposals/0414-region-based-isolation.md#transferring-parameters (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
region based isolationのプロポーザルを見てるとここら辺がモチベーションな気がしました。 Sadly synchronous initializers without additional work can still only take Sendable types since there is not a guarantee that the non-Sendable types that are passed to it is in its own region. In order to pass a non-Sendable type to a synchronous initializer, one must mark the parameter with the transferring function parameter modifier caller側の分離領域とcallee側の分離領域が同じかどうかが保証できないから、callee側の分離領域内にパラメータの値をtransferすることをコンパイラに知らせることで、non-Sendableな値も渡せるようにしたいということなのかなあ、と。 https://github.com/apple/swift-evolution/blob/main/proposals/0414-region-based-isolation.md#using-transferring-to-pass-non-sendable-values-to-async-isolated-actor-initializers (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
あー、朝見た時に勘違いしていたところがわかったかも
11:37 AM
そのままの仕様だと、同じリージョンだと見做されて、チェックされないということが問題なのか
11:37 AM
continuationのようなコンカレンシードメインを跨ぐようなインターフェースは
11:38 AM
そのままだと安全性が担保できていなかったのか
11:39 AM
transferringを指定する事でそのような特殊な関数であることをコンパイラに伝える事ができて
11:40 AM
リージョン解析によって、渡したところで利用が終了することを検査させるようになるんですね
Avatar
はい、僕はそう理解しました。
Avatar
なるほどーありがとうございます
🙌🏻 1
Avatar
これ便利そうですね。 #Predicateを汎用的にしたバージョンみたいです。(Acceptedになってました) // Example models class Library { var albums: [Album] } class Album { var contents: [Photo] var isHidden: Bool } let libraryAlbumCountExpression = #Expression<Library, Int> { library in library.albums.filter { !$0.isHidden }.count } // Evaluate in-memory or pass to some API let numberOfAlbums = try libraryAlbumCountExpression.evaluate(someLibrary) https://forums.swift.org/t/review-sf-0006-expression-macro-and-type/70211
Hello Swift community, The review of SF-0006: #Expression Macro and Type begins now and runs through Thursday, Feb 29, 2024. 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 contacting the review manager directly, please put ...
Avatar
型定義にvariadic genericsが入ってるのが気になったんですがmainではもう実装されてたんですね
t_desudesu 1
Avatar
omochimetaru 3/4/2024 1:05 AM
Greetings Swift evolvers. For your consideration, I have drafted a proposal allowing for more explicit control over the isolation of closures. You can read the proposal at nnnn-closure-isolation.md Please share thoughts and feedback here or as comments on the pull request. Thank you.
1:06 AM
クロージャ式にアイソレーションを指定できるようにする提案 従来は @MainActor のようにグローバルアクター指定するか、指定しないかの2つしかなかったが
1:06 AM
これに nonisolated[isolated actor] を追加する
1:07 AM
また、従来裏技だった @_inheritActorContext の正式版として、 @inheritsIsolation を導入する こいつはただ名前が変わっただけじゃなくて、 isolated引数がある関数ではそれを引き継ぐ、という風にちょっと挙動が違う
1:09 AM
従来って @MainActor のなかで Task.init した時に、 「未指定時の外側からの継承」が強制発動するので、逆に「アクターを引き継がない」ことが書けなかった問題があったので、 (edited)
1:09 AM
これが入るとだいぶわかりやすくなりそう。
👍🏻 1
🥰 1
Avatar
omochimetaru 3/4/2024 8:27 AM
isolated引数がある関数ではそれを引き継ぐ
これは別途話されてる #isolation (だっけ?)と同じ振る舞いってことだと思う
Avatar
#isolation (だっけ?)
おそらくそれかと。 default argument expressions can now have the special form #isolation, which will be filled in with the actor isolation of the caller. If the default argument is for an isolated parameter, this allows isolation to be implicitly passed down. https://github.com/apple/swift-evolution/blob/main/proposals/0420-inheritance-of-actor-isolation.md
(edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 3/4/2024 11:43 AM
これです、あってた
Avatar
omochimetaru 3/8/2024 4:18 AM
variadic generics (type pack) を使っているんですが、コンパイラのバグを踏んだかも?
4:18 AM
頑張って最小化しました
4:18 AM
protocol Controller { associatedtype Deps typealias Routes = GenericRoutes<Self> } struct Request {} protocol Provider { associatedtype ServiceType func provide(for request: Request) throws -> ServiceType } struct GenericRoutes<C: Controller> { public init<P: Provider>( provider: P ) where P.ServiceType == C.Deps { } } struct VariadicProvider< each T: Provider >: Provider { public typealias ServiceType = (repeat (each T).ServiceType) public init(_ providers: repeat each T) { self.providers = (repeat each providers) } public var providers: (repeat each T) public func provide(for request: Request) throws -> ServiceType { return (repeat try (each providers).provide(for: request)) } } protocol DKey { associatedtype Value } struct Dependencies { func get<K: DKey>(_ key: K) -> K.Value { fatalError() } func forRequest<each K: DKey>( _ keys: repeat each K ) -> VariadicProvider<repeat (each K).Value> { return VariadicProvider<repeat (each K).Value>( repeat self.get(each keys) ) } } struct A {} struct B {} struct C {} struct WController: Controller { typealias Deps = (A, B, C) } struct AP: Provider { func provide(for request: Request) throws -> A { fatalError() } } struct BP: Provider { func provide(for request: Request) throws -> B { fatalError() } } struct CP: Provider { func provide(for request: Request) throws -> C { fatalError() } } struct AK: DKey { typealias Value = AP } extension DKey where Self == AK { static var a: AK { AK() } } struct BK: DKey { typealias Value = BP } extension DKey where Self == BK { static var b: BK { BK() } } struct CK: DKey { typealias Value = CP } extension DKey where Self == CK { static var c: CK { CK() } } func main(d: Dependencies) { let vp1: VariadicProvider<AP, BP, CP> = VariadicProvider( d.get(.a), d.get(.b), d.get(.c) ) let r1 = WController.Routes( provider: vp1 ) // write direct vp let r2 = WController.Routes( provider: VariadicProvider( d.get(.a), d.get(.b), d.get(.c) ) ) // build vp from forRequest let vp3: VariadicProvider<AP, BP, CP> = d.forRequest( .a, .b, .c ) let r3 = WController.Routes( provider: vp3 ) // write direct forRequest let r4 = WController.Routes( provider: d.forRequest( .a, .b, .c ) ) }
4:18 AM
4:19 AM
r3 がコンパイルできるのに r4 ができないのはおかしいんじゃないかと
4:22 AM
Swift 5.9.2 はOKで5.10でエラーになってる・・・ https://discord.com/channels/291054398077927425/430242233468452865/1215514280141660240
Avatar
omochimetaru 3/8/2024 10:28 AM
もっと小さく再現しそうだな
Avatar
Hi, folks. I'd like to pitch a new feature that lets you make a higher-order function polymorphic over the isolation of its function parameters. Basically, you can mark a function type as @isolated(any); when you convert a function to that type, the isolation will be statically erased, but it can still be recovered at runtime (as an (any Actor...
12:24 AM
@isolated(any) を関数型に追加する提案
12:24 AM
サラッとと読んでもさっぱりわからなかったのでじっくり読みます
Avatar
わかってきた 重要なことが書いてある
Avatar
omochimetaru 3/13/2024 5:30 AM
まとめ書く前に寝落ちして記憶が飛んだ
5:31 AM
メソッドのような関数宣言においては
5:31 AM
nonisolated、グローバルアクター、isolated引数を指定できる
5:32 AM
クロージャの定義においても、その3種類が書ける
5:34 AM
クロージャもその3種類と、キャプチャ変数によるisolateができる
5:35 AM
関数の型としては、グローバルアクターと、明示的なisolatedパラメータがあって、キャプチャは型に現れない
5:36 AM
で、関数にしようとしたときにこれらのisolationを静的に統一したインターフェースで動的に取得する方法がない (edited)
5:37 AM
なので、Task.initにMainActor指定したクロージャとかを渡す場合
5:37 AM
nonisolatedな関数として渡されて、関数の内部でMainActorにホップする挙動になってしまっている
5:38 AM
@isolated(any)は、関数型の追加属性として、実行時に動的にその関数isolationを取得できるようにする、というもので、
5:39 AM
このアトリビュートがついた関数型は、f.isolationというプロパティが生えていて、これがActor?型として3種類のisolationを値として取得できる
5:40 AM
これによってTask.initは関数を受け取るときにnonisolatedにラップさせる必要がなくなり
5:40 AM
その関数のisolationが要求するexecutorに直接即座に投入できるようになるらしい
5:41 AM
ユーザーからすると、Task.initに@MainActorなクロージャを渡した時に、
5:42 AM
それが呼び出される前後順が、Task.initの前後順を保ってくれるようになって便利
👀 4
5:42 AM
という話みたい
Avatar
Kishikawa Katsumi 3/22/2024 1:47 PM
https://github.com/apple/swift-evolution/blob/main/proposals/0257-elide-comma.md こんな提案あったんですねえ。全然しらなかった。話題にのぼったことあったっけ?
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
1:48 PM
ログあった
Avatar
Kishikawa Katsumi 3/22/2024 1:52 PM
ホントだ。たぶん当時は利点が私にはよくわからなかったんだな。
1:53 PM
いやまあ、今でもカンマは書いたらいいやんと思うけど。
Avatar
omochimetaru 3/22/2024 1:53 PM
ポールさんの話の流れの中で言うと
1:53 PM
カンマが無くせたとしても、if文を混ぜて書けないので
1:53 PM
結局ResultBuilderは欲しいですよね?
Avatar
Kishikawa Katsumi 3/22/2024 1:54 PM
そうですね。今となってはResultBuilderがあるからその選択でよかったと思う。
Avatar
omochimetaru 3/22/2024 1:55 PM
ああそうか、0257時点だとRBが出てきてないからその考え方はできないのか。
Avatar
https://github.com/apple/swift-evolution/blob/main/proposals/0254-static-subscripts.md https://github.com/apple/swift-evolution/blob/main/proposals/0380-if-switch-expressions.md あたりを組み合わせるとけっこうそれっぽいことが出来るようになるけど、限界があるから result builder の方向にいったんじゃないかなぁぁ、っと
Avatar
@swift-main protocol P { associatedtype A } func f<T: P, U>(t: T.Type, u: U.Type) where T.A == U { } struct S: P { typealias A = (foo: Int, bar: Int) } f(t: S.self, u: (foo: Int, bar: Int).self) f(t: S.self, u: (Int, Int).self)
Avatar
Avatar
Iceman
@swift-main protocol P { associatedtype A } func f<T: P, U>(t: T.Type, u: U.Type) where T.A == U { } struct S: P { typealias A = (foo: Int, bar: Int) } f(t: S.self, u: (foo: Int, bar: Int).self) f(t: S.self, u: (Int, Int).self)
swiftNightly BOT 4/10/2024 7:54 AM
exit status: 1 with <stdin>:13:1: error: global function 'f(t:u:)' requires the types '(Int, Int)' and 'S.A' (aka '(foo: Int, bar: Int)') be equivalent 3 | } 4 | 5 | func f<T: P, U>(t: T.Type, u: U.Type) where T.A == U { | `- note: where 'U' = '(Int, Int)', 'T.A' = 'S.A' (aka '(foo: Int, bar: Int)') 6 | } 7 | : 11 | 12 | f(t: S.self, u: (foo: Int, bar: Int).self) 13 | f(t: S.self, u: (Int, Int).self) | `- error: global function 'f(t:u:)' requires the types '(Int, Int)' and 'S.A' (aka '(foo: Int, bar: Int)') be equivalent 14 |
Avatar
whereの制約でタプルが比較される際にラベルの一致も必要になっちゃうんですが、これってうまく回避するほうほうありますか?
7:56 AM
ラベルが違ってても型の順番があっていればオッケーにしたいです。
Avatar
↑ですが、whereに== Tの形だとNGなのでクロージャにして-> Tの形でうけるようにして誤魔化しました
Avatar
Avatar
Yuta Saito
GSoCに新しい面白テーマ増えました: Building Swift Macros with WebAssembly https://www.swift.org/gsoc2024/#building-swift-macros-with-webassembly (edited)
なんかそれ関連っぽい PR が生えてました. https://github.com/apple/swift/pull/73031
This PR introduces support for WebAssembly-based macros via -load-plugin-executable Foo.wasm#Foo. Wasm macros are blazing fast (no SwiftSyntax build required for consumers!) and secure (fully sandb...
Avatar
そうなんすよ。流石にこのまま入ることは無い気はするけどモチベがある人がいることは良いことだ
8:17 AM
Swift公式ブック的にはsomeとanyは opaque types と boxed protocol types って言うらしい
t_naruhodo 4
Avatar
日本語に訳しているときに僕も初めて知りました。boxed protocol typesというワードを使っている人見たことないですねw
Avatar
そうそう。翻訳の通知で気づいた。
t_naruhodo 1
Avatar
これって網羅性チェック通らないのか
7:01 AM
まあ↓こうすればいいけど
Avatar
omochimetaru 4/27/2024 7:01 AM
あれ?僕やった時効いたけどな
Avatar
え、ほんと?
Avatar
omochimetaru 4/27/2024 7:02 AM
do throwsじゃなくて普通のdoにしたのと
7:02 AM
experimentalのFullTypedThrowsをつける
7:02 AM
upcomingではないですよ
7:03 AM
あとassociated valueは無し
Avatar
普通のdoは最初に試してダメだったのでthrowsを追加して試してたので関係なさそう
Avatar
うーん、ダメっぽい
Avatar
omochimetaru 4/27/2024 7:25 AM
あー
Avatar
> Note: Exhaustiveness checking in the general is expensive at compile time, and the existing language uses the presence of an unconditional catch block as the indicator for an exhaustive do...catch. See the section on closure thrown type inference for more details about inferring throwing closures.
Avatar
omochimetaru 4/27/2024 7:25 AM
できたと思ってたけど、外側にthrowsがついてて、実はできてないのを見逃していたかも
Avatar
なるほど
7:25 AM
トップレベルとかも見逃しがち
Avatar
omochimetaru 4/27/2024 7:27 AM
たしかに
Avatar
網羅性チェックしてるやんwww
t_kusa 1
🤣 1
Avatar
omochimetaru 4/27/2024 7:30 AM
わかっとるやんけ
Avatar
まだできない?
Avatar
omochimetaru 4/27/2024 8:05 AM
それは見たこと無かったけど、なるほど
Avatar
Proposalにはあるけどまだ無理っぽかった。async letとtyped throwsの組み合わせも。↑も未実装なだけかも。 (edited)
Avatar
おもしろい class AnimalError: Error {} class CatError: AnimalError {} do { let never: () -> Void = {} let cat: () throws(CatError) -> Void = never let animal: () throws(AnimalError) -> Void = cat let creature: () throws -> Void = animal } do { let creature: (() throws -> Void) -> Void = { _ in } let animal: (() throws(AnimalError) -> Void) -> Void = creature let cat: (() throws(CatError) -> Void) -> Void = animal let never: (() -> Void) -> Void = cat }
Avatar
バリアンスちゃんとしてますね
Avatar
Let's talk about data race safety in Swift 6! The Swift 6 language mode is opt-in; you can continue to use Swift 5 mode with the Swift 6 compiler. You can incrementally refine your code to take advantage of full data isolation at your own pace, module by module.
11:48 AM
Swift6コンパイラのデフォルトの挙動はSwift5モードらしい。
Avatar
SwiftPM の方だと swift-tools-version が 6.0 以上の場合は Swift 6 モードをデフォルト挙動にするような変更を加えようとしてましたけどね. https://github.com/apple/swift-package-manager/pull/7469 (edited)
Avatar
ほんまや。これは良いのかなあ
12:07 PM
I'm repeating this clarification everywhere because a lot of people (not necessarily you) are confused by this: the data-race safety warnings will only become errors when you explicitly adopt -swift-version 6. Simply using the Swift 6.0 compiler without any changes to your project settings will not make these warnings become errors in your project.
Avatar
(まあ既存のプロジェクトのデフォルト挙動が急に変わらないという意味ではさっきの PR がマージされても一緒ですが) (edited)
Avatar
「プロジェクト設定を変えなければ壊れない」という意味なら良さそうですね。
12:08 PM
新規のプロジェクトのデフォルトは6であると
Avatar
@StateとListとpresentationDetentsが組み合わさると、presentationDetentsの指定が無視されるんですがこれって既知ですか? import SwiftUI struct ContentView: View { @State var showSheet = false @State var name = "" var body: some View { Button("show sheet") { showSheet = true } .sheet(isPresented: $showSheet) { List { TextField("", text: $name) } .presentationDetents([.medium]) } } } ListをVStackにしたり、TextFieldをTextにすると発生しません。謎挙動
Exported 31,483 message(s)
Timezone: UTC+0