テーマ 第一部: モダンなプログラミング言語としてのSwift Swiftの言語仕様やコンパイラなどについて語ります。 キーワード Swift 4.1 SwiftとObjective-C Swiftと他の言語 マルチプラットフォーム Conditional conformance Memory ownership 第二部: iOSアプリの開発言語としてのSwift iOSアプリを開発するにあたって、よりSwiftyな手法やAppleのフレームワークとの上手な付き合い方などについて語ります。 キーワード UIKitとIUO より安全にUIKitを扱う方法struct Box<T> { let value: T } extension Box: Equatable where T: Equatable { static func == (lhs: Box, rhs: Box) -> Bool { return lhs.value == rhs.value } }func ==<X>(a: [X], b: [X]) where X: Equatable { ... } (edited)//:configuration = Release OTHER_SWIFT_FLAGS = -enable-experimental-conditional-conformances //:completeSettings = some OTHER_SWIFT_FLAGSfunc == いらない?// Will not currently compile protocol Sequence { associatedtype SubSequence: Sequence where Iterator.Element == SubSequence.Iterator.Element, SubSequence.SubSequence == SubSequence // Returns a subsequence containing all but the first 'n' items // in the original sequence. func dropFirst(_ n: Int) -> Self.SubSequence // ... }// Test for a simulator destination #if (arch(i386) || arch(x86_64)) && (!os(macOS)) print("Simulator") #else print("Device") #endif // More restrictive test for iOS simulator // Adjust the os test for watchOS, tvOS #if (arch(i386) || arch(x86_64)) && os(iOS) // iOS simulator code #endifprotocol で init を書くと self を上書きできるcoder aDecoder: NSCoder を実装すればstatic func make() -> Self を実装すれば良いのではinit(withNibName: ) にnilをつっこむと、その<クラス名>.nibから生成できるprotocol Factoryable { init(factory: () -> Self) } extension Factoryable { init(factory: () -> Self) { self = factory() } } class MyAnimal: Factoryable { convenience init(name: String) { if name.contains("Cat") { self.init { MyCat() } } else { self.init { MyDog() } } } } class MyCat: MyAnimal { var meou: String { return "meou" } } class MyDog: MyAnimal { } let x = MyCat(name: "Dog") x.meou // Crash!!import Foundation protocol Factoryable { init(factory: () -> Self) } extension Factoryable { init(factory: () -> Self) { self = factory() } } class MyAnimal: Factoryable { convenience init(name: String) { if name.contains("Cat") { self.init { MyCat() } } else { self.init { MyDog() } } } } class MyCat: MyAnimal { var meou: String { return "meou" } } class MyDog: MyAnimal { func bark(arg: String) -> String { return arg } } let x = MyCat(name: "Dog") let y = x.meou // Crash!!rintaro - 2017/05/19 https://gist.github.com/rintaro/b16f05411cfe540754285dcc0da60174 Gist factory_init.swift これも Dog(type: "cat") 呼べちゃうっていう問題がきつい この辺で話題になった// RUN: %target-typecheck-verify-swift -swift-version 4dynamic_self_swift4 // Semi-bogus factory init pattern static func init の話もしてたけど、それは少なくともまだ戻り値の型がちゃんと正しい型でしたな、こいつ Dog なのにデバッグ情報としての型は Cat (edited)init(factory: () -> Self)のwitness-tableには、Cat,Dogはなくて、Animalだけがある、だから、convenience initはCat/Dogからは呼べない、が正しいと思うんですよねself = factory() が書けるのが問題な気が…通常のclassの convenience init でも self = ... はエラーになるはずprotocol SomeProtocol: nonclass くる?class Animal { factory init(name: String) { ... } } class Cat: Animal { init() { super.init(name: "Cat") } } // Compile Error Cat.init(name: "Cat") // Compile Errorinit(throws x: String) throws { // この中でOptionalなsuper.init(convenienceでself.init)を呼んでnilならErrorを出したい } これめちゃくちゃ困ってるんですが、classだけで完結できる方法ありますかね?struct Box<T> { let value: T } extension Box: Equatable where T: Equatable { static func == (lhs: Box, rhs: Box) -> Bool { return lhs.value == rhs.value } } これが普通に動いてる気がするdictionaryRepresentationしてからファイルにしたらいいんじゃないかな。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] } この状態でCにfooを補完させると func foo<T>(t: T) where T : HasB, [E] == T.B { } というコンパイルの通らないコードが補完されるCurPtr = BufferEnd 確かにこれいきなり出てきたらギョッとする{ ∃X where X: P, X } より { ∃X ∈ P, X } のほうがいいかもなって思ったbody が T を受けてくれたらいいのに・・・。self.disposeBag = nil // その他処理... } みたいなときに、 deinit の発行が その他処理の「後」になることがあり得るか?という話に関しては、無いかなーと思っていますが、検証はしていません。 (edited)protocol P {} protocol Foo { var foo: Int { get } } extension Int: P {} extension Array: Foo where Element: P { var foo: Int { return count } } let a = [1,2,3] print(a is Foo) (edited)main.swift:12:9: warning: 'is' test is always true print(a is Foo) ^ warning: Swift runtime does not yet support dynamically querying conditional conformance ('Swift.Array<Swift.Int>': 'main.Foo') Could not cast value of type 'Swift.Array<Swift.Int>' (0x7f6f03a20240) to 'main.Foo' (0x7f6f03a20280). #0 0x0000000003f24d64 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x3f24d64) #1 0x0000000003f250a6 SignalHandler(int) (/usr/bin/swift+0x3f250a6) #2 0x00007f6f07f2c390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #3 0x00007f6f0666b428 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x35428) #4 0x00007f6f0666d02a abort (/lib/x86_64-linux-gnu/libc.so.6+0x3702a) #5 0x00007f6f038fbf13 (/usr/lib/swift/linux/libswiftCore.so+0x39df13) #6 0x00007f6f038f84d9 (/usr/lib/swift/linux/libswiftCore.so+0x39a4d9) #7 0x00007f6f038f852b (/usr/lib/swift/linux/libswiftCore.so+0x39a52b) #8 0x00007f6f038f9a78 _dynamicCastToExistential(swift::OpaqueValue*, swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetExistentialTypeMetadata<swift::InProcess> const*, swift::DynamicCastFlags) (/usr/lib/swift/linux/libswiftCore.so+0x39ba78) #9 0x00007f6f0835b2ad #10 0x00007f6f0835b10e #11 0x0000000000fed1ce llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) (/usr/bin/swift+0xfed1ce) #12 0x0000000000ff1692 llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, char const* const*) (/usr/bin/swift+0xff1692) #13 0x00000000004d9076 swift::RunImmediately(swift::CompilerInstance&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, swift::IRGenOptions&, swift::SILOptions const& (edited)truestderr:main.swift:12:9: warning: 'is' test is always true print(a is Foo) ^protocol P {} protocol Foo { var foo: Int { get } } extension Int: P {} extension Array: Foo where Element: P { var foo: Int { return count } } let a = [1,2,3] print(a is Foo)protocol P {} protocol Foo { var foo: Int { get } } extension Int: P {} extension Array: Foo where Element: P { var foo: Int { return count } } let a = [1,2,3] print(a is Foo)swift-4.0-RELEASE/usercode/main.swift:7:1: error: extension of type 'Array' with constraints cannot have an inheritance clause extension Array: Foo where Element: P { ^ ~~~swift-4.0.2-RELEASE/usercode/main.swift:7:1: error: extension of type 'Array' with constraints cannot have an inheritance clause extension Array: Foo where Element: P { ^ ~~~swift-4.0.3-RELEASE/usercode/main.swift:7:1: error: extension of type 'Array' with constraints cannot have an inheritance clause extension Array: Foo where Element: P { ^ ~~~swift-4.1-RELEASE/usercode/main.swift:12:9: warning: 'is' test is always true print(a is Foo) ^ warning: Swift runtime does not yet support dynamically querying conditional conformance ('Swift.Array<Swift.Int>': 'main.Foo') Could not cast value of type 'Swift.Array<Swift.Int>' (0x7fc841935240) to 'main.Foo' (0x7fc841935280). /usr/bin/swift[0x3f24d54] /usr/bin/swift[0x3f25096] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7fc845641390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7fc843d80428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7fc843d8202a] /usr/lib/swift/linux/libswiftCore.so(+0x39df13)[0x7fc841810f13] /usr/lib/swift/linux/libswiftCore.so(+0x39a4d9)[0x7fc84180d4d9] /usr/lib/swift/linux/libswiftCore.so(+0x39a52b)[0x7fc84180d52b] /usr/lib/swift/linux/libswiftCore.so(+0x39ba78)[0x7fc84180ea78] [0x7fc845a702ad] [0x7fc845a7010e] /usr/bin/swift[0xfed1ce] /usr/bin/swift[0xff1692] /usr/bin/swift[0x4d9076] /usr/bin/swift[0x4c35d3] /usr/bin/swift[0x4beecc] /usr/bin/swift[0x4778c4] ...swift-4.1.1-RELEASE/usercode/main.swift:12:9: warning: 'is' test is always true print(a is Foo) ^ warning: Swift runtime does not yet support dynamically querying conditional conformance ('Swift.Array<Swift.Int>': 'main.Foo') Could not cast value of type 'Swift.Array<Swift.Int>' (0x7f2e73ecc240) to 'main.Foo' (0x7f2e73ecc280). /usr/bin/swift[0x3f24d64] /usr/bin/swift[0x3f250a6] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f2e77bd8390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7f2e76317428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7f2e7631902a] /usr/lib/swift/linux/libswiftCore.so(+0x39df13)[0x7f2e73da7f13] /usr/lib/swift/linux/libswiftCore.so(+0x39a4d9)[0x7f2e73da44d9] /usr/lib/swift/linux/libswiftCore.so(+0x39a52b)[0x7f2e73da452b] /usr/lib/swift/linux/libswiftCore.so(+0x39ba78)[0x7f2e73da5a78] [0x7f2e780072ad] [0x7f2e7800710e] /usr/bin/swift[0xfed1ce] /usr/bin/swift[0xff1692] /usr/bin/swift[0x4d9076] /usr/bin/swift[0x4c35d3] /usr/bin/swift[0x4beecc] /usr/bin/swift[0x4778c4] ...swift-4.2-DEVELOPMENT-SNAPSHOT-2018-05-02-atrue/usercode/main.swift:12:9: warning: 'is' test is always true print(a is Foo) ^protocol P {} protocol Foo { var foo: Int { get } } extension Int: P {} extension Array: Foo where Element: P { var foo: Int { return count } } let a = [1,2,3] print(a is Foo)swift-4.2-DEVELOPMENT-SNAPSHOT-2018-05-02-atrue/usercode/main.swift:12:9: warning: 'is' test is always true print(a is Foo) ^where Key == Value やばそうprotocol A { static func foo() } extension Dictionary: A where Key == Value { static func foo() { print(type(of: self)) } } extension Array where Element: A { static func foo() { Element.foo() } } [String: String].foo() // Dictionary<String, String> [[String: String]].foo() // Dictionary<Dictionary<String, String>, Dictionary<String, String>>protocol A { static func foo() } extension Dictionary: A where Key == Value { static func foo() { print(type(of: self)) } } extension Array where Element: A { static func foo() { Element.foo() } } [String: String].foo() // Dictionary<String, String> [[String: String]].foo() // Dictionary<Dictionary<String, String>, Dictionary<String, String>>swift-4.2-DEVELOPMENT-SNAPSHOT-2018-05-02-aDictionary<String, String>.Type Dictionary<String, String>.Typeprotocol A {} protocol B: A {} protocol C: A {} protocol D: B, C {} struct X<T>: A{} extension X: D where T == Int { // Type 'X<T>' does not conform to protocol 'B' }main.swift:11:1: error: conditional conformance of type 'X<T>' to protocol 'D' does not imply conformance to inherited protocol 'B' extension X: D where T == Int { // Type 'X<T>' does not conform to protocol 'B' ^ main.swift:11:1: error: conditional conformance of type 'X<T>' to protocol 'D' does not imply conformance to inherited protocol 'C' extension X: D where T == Int { // Type 'X<T>' does not conform to protocol 'B' ^ main.swift:11:1: note: did you mean to explicitly state the conformance like 'extension X: C where ...'? extension X: D where T == Int { // Type 'X<T>' does not conform to protocol 'B' ^import PlaygroundSupport するのはPlaygroundBookでしかできない? Linked Frameworks からaddするのかと思ったらそれもできないし@objc protocol Foo { optional func aaa() }let a: [String] = [] let b: [Int] = a as! [Int] (edited)@escaping/@noescape はオーバーロードできる?func a(_ f: @escaping () -> ()) { } func a(_ f: () -> ()) { }func a(_ f: @escaping () -> ()) { } func a(_ f: () -> ()) { }swift-4.1.1-RELEASE/usercode/main.swift:2:6: error: invalid redeclaration of 'a' func a(_ f: () -> ()) { } ^ /usercode/main.swift:1:6: note: 'a' previously declared here func a(_ f: @escaping () -> ()) { } ^@objc をつけると作れるprotocol A {} class B: A{} class C: A{} vs enum A { case b(B) case c(C) }class A { func hoge(a: Sub) -> Sub { return Sub() } } class B: A { override func hoge(a: Super) -> SubSub { return SubSub() } } class Super {} class Sub: Super {} class SubSub: Sub {} (edited)class A { func hoge(a: Sub) -> Sub { return Sub() } } class B: A { override func hoge(a: Super) -> SubSub { return SubSub() } } class Super {} class Sub: Super {} class SubSub: Sub {}swift-4.1.1-RELEASEAny と String のときダメなんです??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") } } 今でもこういうことはできると聞きましたenum vs protocol をやっていきたいと思います。 protocol A {} class B: A{} class C: A{} vs enum A { case b(B) case c(C) }sealdがないので、protocolを利用した上の例では、予想しないような実装(クラス・構造体)が作られる恐れがあり、またパターンマッチで網羅性を検査することができません。enumがいいのか、という議論になるかというとそうではなくて、(勘違いだったら申し訳ないんですが)Swiftのenumの各タグ(?、たとえば上記の例でいうaとかb)はたしか型パラメーターが取れないです。protocolをつかって次のようにやるしかない、といった感じになるんじゃないでしょうか。 public protocol HList { } public struct HNil: HList { init() { } } public struct HCons<H, T: HList>: HList { public let head: H public let tail: T public init(_ h: H, _ t: T) { self.head = h self.tail = t } }HNilとHConsがありますが、HConsが型パラを取るので、こうしています。enumだと各タグ(?)は型パラメーターが取れないから、enumではできそうにない、という例として使いました。 (edited)enum HList0 { case `nil` } enum HList1<T1> { case `nil` case list0(HList0) } enum HList2<T1, T2> { case `nil` case list1(HList1<T2>) } enum HList3<T1, T2, T3> { case `nil` case list2(HList2<T3, T3>) }HCons と HNil の二つがあればいいんじゃない?public protocol HList { } public struct HNil: HList { init() { } } public struct HCons<H, T: HList>: HList { public let head: H public let tail: T public init(_ h: H, _ t: T) { self.head = h self.tail = t } }// Kotlin sealed class HList { class HNil: HList() class HCons<H, T: HList>(val head: H, val tail: T): HList() }head と tail にマッチングできないかな?
HCons<Int, HCons<String, HCons<Bool, HNil>>> とは、先頭の値の型が Int であり、かつ2番目の値の型が String であり、そして3番目の値の型が Bool であることを示している。switch list { case let .Cons(v): ??? case let .Nil: ??? } みたいな switch list { case let .Cons(v): ??? case let .Cons(.Cons(v)): ??? }protocol HListProtocol { associatedtype HeadType associatedtype ConsType: HListProtocol func asEnum() -> EHList<HeadType, ConsType> } indirect enum EHList<H, L: HListProtocol> { case `nil` case cons(H, EHList<L.HeadType, L.ConsType>) }switch hlist { // たとえばhlistの型は HCons<Int, HCons<String, HCons<Bool, HNil>>> だとする。これはコンパイラなら知ってるぞ case let .HCons(v): ??? // 当然 :point_up: の先頭の型は Int だから、vはIntだぞ case let .HNil: ??? }HListならまあ、どうにかJavaでもできそうなんですけど、HListの値があったとき、それらをアペンドする関数をかけるか?というのは実はSwiftとかじゃないとキビしいと思います。HCons<Int, HCons<String, HCons<Bool, HNil>>>とHCons<Int, HCons<String, HCons<Bool, HNil>>>があったら、アペンドするとHCons<Int, HCons<String, HCons<Bool, HCons<Int, HCons<String, HCons<Bool, HNil>>>>>>という型が帰ってくる関数です。extensionが型パラメーター取れないんだった!extension Optional { func flatten<T>() -> T? where Wrapped == T? { return flatMap { $0 } } }extension<T> Optional where Wrapped == T? { func flatten() -> T? { return flatMap { $0 } } }extensionで型パラ取らせてくれーassosicatedtypeしているので、関数の中というよりは、extensionの中ですぐ必要な感じです。public protocol HAppend { associatedtype A: HList associatedtype B: HList associatedtype C: HList static func append(_ hl1: A, _ hl2: B) -> C } extension<D: HList> HAppend { typealias A = HNil typealias B = D typealias C = D static func append(_ hl1: Nil, _ hl2: D) -> D = hl2 } (edited)Natを作って、それつかってHLIstにアクセスしているけど、同様にこういうのもつくれない……)interface Event { timestamp: number; } interface MouseEvent extends Event { x: number; y: number } function listenEvent(eventType: EventType, handler: (n: Event) => void) { /* ... */ } // Unsound, but useful and common listenEvent(EventType.Mouse, (e: MouseEvent) => console.log(e.x + "," + e.y));Qonceptのエンジニア。Swiftについて思ったことをつらつらとQiitaに書いてたら、なぜかtry! Swiftで発表することになった。最近は機械学習関係の業務も多く、Swiftで機械学習できないか模索中。@"$S4main3CatVAA6AnimalAAWP" = hidden constant [3 x i8*] [i8* bitcast (%swift.protocol_conformance_descriptor* @"$S4main3CatVAA6AnimalAAMc" to i8*), i8* bitcast (%swift.metadata_response (i64)* @"$SSiMa" to i8*), i8* bitcast (void (%TSi*, %T4main3CatV*, %swift.type*, i8**)* @"$S4main3CatVAA6AnimalA2aDP3foo5ValueQzyFTW" to i8*) ], align 8typedef について大阪 C++ 勉強会でちょっと話題が出ていて,そういえば typedef がどうしてダメで型エイリアスだと良いのかみたいな話あまりまとまってない気がしたのでメモ. typedef はこんな感...auto return types without trailing type information). Joe mentioned that there was some interest in switching the rest of swift to C++14 as well. I figured that I would just start a thread here t...enum class WriteImplKind { /// It's immutable. Immutable, /// There's storage. Stored, /// There are observers on top of the storage. /// TODO: maybe add a StoredWithDidSet here and to ReadWriteImplKind? StoredWithObservers, /// There are observers on top of the superclass's write implementation. InheritedWithObservers, /// There's a setter. Set, /// There's a mutable addressor. MutableAddress, /// There's a modify coroutine. Modify, };otoolコマンドでリンクしているlibswiftCore を調べられるrdar://problem/16997751 って見れないんでしたっけ func test1() throws { let parser = Parser(string: "$S13ExampleNumber6isEven6numberSbSi_tKF") let node = try parser.parse() XCTAssert(node.isEqualString( Node.symbol(start: .start(pos: 0, string: "$S"), entity: .entity(context: .module(Identifier(pos: 0, string: "ExampleNumber")), body: .function(name: Identifier(pos: 0, string: "isEven"), labelList: [ Identifier(pos: 0, string: "number") ])) ) ) ) }▿ SwiftDemangler.Node.symbol ▿ symbol: (2 elements) ▿ start: SwiftDemangler.Node.start ▿ start: (2 elements) - pos: 0 - string: "$S" ▿ entity: SwiftDemangler.Node.entity ▿ entity: (2 elements) ▿ context: SwiftDemangler.Node.module ▿ module: SwiftDemangler.Identifier - pos: 2 - string: "ExampleNumber" ▿ body: SwiftDemangler.Node.function ▿ function: (4 elements) ▿ name: SwiftDemangler.Identifier - pos: 17 - string: "isEven" ▿ labelList: 1 element ▿ SwiftDemangler.Identifier - pos: 24 - string: "number" ▿ retType: SwiftDemangler.Type.single ▿ single: (1 element) - name: "Swift.Bool" ▿ argType: SwiftDemangler.Type.list ▿ list: 1 element ▿ SwiftDemangler.Type.single ▿ single: (1 element) - name: "Swift.Int"for character in source { switch character { case "{": tokens.append(.leftBrace(...)) case "(": tokens.append(.leftParen(...)) case "'": tokens.append(.singleQuote(...)) ... case " ". "\t", "\n": tokens.append(.whitespace(...)) ... default: tokens.append(.character(...)) } } ^ みたいにして先読みもバックトラックもせずに一気にループで一回 String を [Token] にして、その後 [Token] をもう一度頭からループして今度は先読みしたり戻ったりをしながら意味のある構造に区切っていくのがシンプルじゃないかな。 [Token] だったら String を行ったり来たりするよりもよほど簡単。[Token] を作る処理で、どうせもう一度読むので [Character] より多少マシ、くらい。そういう意味だと [Character] でもいいけどどうせ一回 String を全部読むなら多少は情報を追加しといたほうがいいかな、という感じですね。classとか funcの予約語やIdentifierに分けるのは簡単だし、Stringの端から端まで読み飛ばすのも楽だし、というのが楽になるくらい。enum Token { case whitespace(raw: String, line: Int, column: Int) ... } のようにするかも?enum E { case c(Bool) } let e = E.c(true) switch e { case .c(let b) where b == true: print(1) case .c(let b) where b == false: print(2) case .c(true): print(3) case .c(false): print(4) }print(type(of: AnyCollection<String>(["hello"]).startIndex)) print(type(of: AnyCollection<Character>("hello").startIndex)) print(type(of: ["hello"].startIndex)) print(type(of: "hello".startIndex))AnyIndex AnyIndex Int Indexvar _p: XXX! // ① struct S { var p: some P { get { ... } set { ... } } } _p = S().p S().p = _p as! XXX // ② こういうことやりたい場合、①か②で「S.pのORT型」を明示的に表現しなきゃいけないけど、どうやって書けばいいんだろう (edited)struct S { func a() -> some P func b() -> some P } 今言ったの、このふたつが共存できないって話??func f() -> some P1 func f() -> some P2 が駄目ということlet p: P1 = f()struct S { func f() -> some P } let ss: [S] = ... let arr: [XXX] if cond { arr = ss.map { $0.f() } } else { arr = ... } (edited)func g<X: P1>(_ x: X) { } g(f())./docs/TypeChecker.rst:126: called. Conversion constraints are written ``X <c Y``, read as ./docs/TypeChecker.rst:261: conversion constraint ``T(b) <c T0`` captures the requirement that ./docs/TypeChecker.rst:284: respectively. The constraint ``T(b) <c T0`` requires the key ./docs/TypeChecker.rst:324: constraints ``T(y) <c T0`` and ``T(z) <c T0`` capture the need for ./docs/TypeChecker.rst:503: A -> B <c C -> D ./docs/TypeChecker.rst:594:placed on it that relate it to concrete types, e.g., ``T0 <c Int`` or ./docs/TypeChecker.rst:595:``Float <c T0``. In these cases, we can use the concrete types as a ./docs/TypeChecker.rst:741:these constraints is broken down into "``T2 <c Int``" and "``X <c ./docs/TypeChecker.rst:763:applied. Similarly, the "``(T2, X) <c T0`` constraint has a ./docs/TypeChecker.rst:772:example, the ``T2 <c Int`` constraint will be anchored at the function ./docs/TypeChecker.rst:776:element. Similarly, the ``X <c String`` constraint will have the same ./docs/TypeChecker.rst:789:simplifying the constraint ``X <c String``, so it uses the locator ./docs/TypeChecker.rst:842:Here, the failing constraint is ``Float <c Int``, with the same ./lib/Sema/CSSimplify.cpp:6596: // T <c U ===> T? <c U! ./lib/Sema/CSSimplify.cpp:6715: // T < U or T is bridged to V where V < U ===> Array<T> <c Array<U> ./lib/Sema/CSSimplify.cpp:6730: // Dictionary<K1, V1> <c Dictionary<K2, V2> ./lib/Sema/CSSimplify.cpp:6764: // T1 < T2 || T1 bridges to T2 ===> Set<T1> <c Set<T2> ./lib/Sema/CSSimplify.cpp:6778: // T1 <c T2 && T2 : Hashable ===> T1 <c AnyHashable ./lib/Sema/CSSimplify.cpp:6809: // T' < U and T a toll-free-bridged to T' ===> T' <c U ./lib/Sema/CSSimplify.cpp:6824: // T < U' and U a toll-free-bridged to U' ===> T <c U <C where C : ...> みたいなのが引っかかりまくる ./test/SIL/Parser/witness_with_inherited_gp.sil:59:// IndexingIterator<_mmArrayBuffer<T>>: specialize <C = _mmArrayBuffer<T>, ./docs/Generics.rst:574:and the constraints expressed in the angle brackets (e.g., <C : ./docs/TypeChecker.rst:130: A construction constraint, written ``X <C Y`` requires that the ./docs/TypeChecker.rst:268: a construction constraint ``T(b) <C A``, which requires that ``A`` rstが古くて消えてないだけってのは正しそうThis copy of libswiftCore.dylib requires an OS version prior to 10.14.4. Abort trap: 6 の対策って文脈で合ってます? (edited).id で比較してました。{ (x) -> Int in 4 }(3)valueToOptional なんだから OptionalType だろうと思って、乱暴に as! でキャストしてるInjectIntoOptionalExpr and coerceInt? だとしたら、3 を Int にcoerceして、それを Int? に包む感じなのかな。let expr = してる。let expr = したんだろうな。if let resultTy = node.returnType { if let lastBody = node.body.popLast() as? Expr { let expr = try solution.coerce(expr: lastBody, to: resultTy) node.body.append(expr) } }as? が成り立たなかったら、bodyの最後が消えてるな。。。node.body = try [solution.coerce(expr: node.body.last as! Expr, to: (node.type as! FunctionType).result)]if let retTy = node.returnType, let last = node.body.removeLast() as? Expr { node.body.append(try solution.coerce(expr: last, to: retTy)) }returnType を使ってる。同じ間違いしてる。f([Cat()]) ^ あとでこのArrayリテラルをSetでうけるやつを試すclass Cat {} func f(_ a: AnyObject) { } f(Cat.self)<stdin>:5:3: error: argument type 'Cat.Type' does not conform to expected type 'AnyObject' f(Cat.self) ^// 0 0 0 0 0 0 1 0 0 0 0 0: SK_NonDefaultLiteralが1 func f(a: Set<Int>) { print("a") } // func f(a: [Int]) { print("b") } f(a: [0]) // b (edited)// 0 0 0 0 0 0 1 0 0 0 0 0: SK_NonDefaultLiteralが1 func f(a: Set<Int>) { print("a") } // そもそも出ない @available(*, unavailable) func f(a: [Int]) { print("b") } f(a: [0]) // a (edited)わいわいswiftc #17 で森タワー(ヒルズ)に入るパスワードみたいなのってもう配信されてましたっけ?func outer<A>() { func inner() { } // A is artchetype inner() }any Pany P と <T: P> Tstruct A<T> { var value: T } print(MemoryLayout<Int>.size) print(MemoryLayout<String>.size) print(MemoryLayout<A<Int>>.size) print(MemoryLayout<A<String>>.size) (edited)A<Int> = { var value: Int } A<String> = { var value: String }Var はVarってクラスだからこうなるんだけど、パッと見大文字始まりだと違和感あるな例えば、 λx. x と λy. y は同じ関数を表している。((λx.M) E) → (M[x := E]) β-reduction Replacing the bound variables with the argument expression in the body of the abstraction.protocol HTraverse { associatedtype Source: HList func traverse(_ f: () -> Void) -> HNil } extension HCons: HTraverse where T: HTraverse { typealias Source = HCons<H, T> // おい!ここを@inlinableにさせてくれ!! func traverse(_ f: () -> Void) -> HNil { f() return self.tail.traverse(f) } } extension HNil: HTraverse { typealias Source = HNil public func traverse(_ f: () -> Void) -> HNil { f() return HNil() } }
HListをHNil まで型レベルで再帰していくことによって、たとえば HCons<String, HCons<Bool, HCons<Bool, HCons<Int, HCons<Optional<Int>, HCons<String, HCons<Bool, HCons<Bool, HCons<Int, HCons<Optional<Int>, HNil>>>>>>>>>> このように10回HCons がネストした型だと10回の違った(1つずつ展開された)呼び出され型がするため、その分の特殊化(?)でバイナリサイズが爆弾になることを期待してたんですが、コメントにあるとおり、狙った場所に @inlineable を書くとコンパイルがとおらない…… mayHaveSideEffects関数の実装の話かmapのoptimizationのはなしします_addr suffixに何の情報もなくて辛い命名だn 以外今の所無さそう //===----------------------------------------------------------------------===// // // This file defines the database of builtin functions. // // BUILTIN(Id, Name, Attrs) // - Id is an identifier suitable for use in C++ // - Name is a string literal for the name to which the builtin should be // bound in Swift // - Attrs specifies information about attributes of the function: // n -> readnone // //===----------------------------------------------------------------------===//c++ class FullApplySite : public ApplySite { explicit FullApplySite(void *p) : ApplySite(p) {} public: FullApplySite() : ApplySite() {} explicit FullApplySite(SILInstruction *inst) : ApplySite(inst) { assert(classof(inst) && "not an apply instruction?"); } FullApplySite(ApplyInst *inst) : ApplySite(inst) {} FullApplySite(BeginApplyInst *inst) : ApplySite(inst) {} FullApplySite(TryApplyInst *inst) : ApplySite(inst) {} static FullApplySite isa(SILNode *node) { auto *i = dyn_cast<SILInstruction>(node); if (!i) return FullApplySite(); auto kind = FullApplySiteKind::fromNodeKind(i->getKind()); if (!kind) return FullApplySite(); switch (kind.getValue()) { case FullApplySiteKind::ApplyInst: return FullApplySite(cast<ApplyInst>(node)); case FullApplySiteKind::BeginApplyInst: return FullApplySite(cast<BeginApplyInst>(node)); case FullApplySiteKind::TryApplyInst: return FullApplySite(cast<TryApplyInst>(node)); } llvm_unreachable("covered switch"); }NON_VALUE_INST(StoreInst, store, SILInstruction, MayWrite, DoesNotRelease) NON_VALUE_INST(AssignInst, assign, SILInstruction, MayWrite, DoesNotRelease)@xedin (edited)func f(aa: Int, bb: Int) {} func f(cc: Int, dd: Int) {} func main() { f(aa: 1, 2) }
7<stdin>:5:5: error: argument labels '(aa:, _:)' do not match any available overloads f(aa: 1, 2) ^~~~~~~~~~~ <stdin>:5:5: note: overloads for 'f' exist with these partially matching parameter lists: (aa: Int, bb: Int), (cc: Int, dd: Int) f(aa: 1, 2) ^<stdin>:5:6: error: missing argument label 'bb:' in call f(aa: 1, 2) ^ bb:
2f { } {} {} {} (ry うごくの?func f(_ a: (Void) -> Void...) { } f {} {} {} {} {} {}<stdin>:3:5: error: consecutive statements on a line must be separated by ';' f {} {} {} {} {} {} ^ ; <stdin>:3:6: error: top-level statement cannot begin with a closure expression f {} {} {} {} {} {} ^ <stdin>:3:11: error: consecutive statements on a line must be separated by ';' f {} {} {} {} {} {} ^ ; <stdin>:3:12: error: top-level statement cannot begin with a closure expression f {} {} {} {} {} {} ^ <stdin>:3:17: error: consecutive statements on a line must be separated by ';' f {} {} {} {} {} {} ^ ; <stdin>:3:18: error: top-level statement cannot begin with a closure expression f {} {} {} {} {} {} ^ <stdin>:1:13: warning: when calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'? func f(_ a: (Void) -> Void...) { } ^~~~~~ () <stdin>:3:9: error: argument passed to call that takes no arguments f {} {} {} {} {} {} ^~ <stdin>:3:15: error: argument passed to call that takes no arguments f {} {} {} {} {} {} ^~ <stdin>:3:18: error: closure expression is unused f {} {} {} {} {} {} ^ <stdin>:3:18: note: did you mean to use a 'do' statement? f {} {} {} {} {} {} ^ do Usage: @swiftNightly [SWIFT_OPTIONS] ``` [Swift Code] ```func f( a: (Void) -> Void...) { } f {} : {}<stdin>:3:5: error: consecutive statements on a line must be separated by ';' f {} : {} ^ ; <stdin>:3:6: error: expected expression f {} : {} ^ <stdin>:3:8: error: top-level statement cannot begin with a closure expression f {} : {} ^ <stdin>:1:12: warning: when calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'? func f( a: (Void) -> Void...) { } ^~~~~~ () <stdin>:3:8: error: closure expression is unused f {} : {} ^ <stdin>:3:8: note: did you mean to use a 'do' statement? f {} : {} ^ do func f( a: (Void) -> Void...) { } f {} _: {}<stdin>:1:12: warning: when calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'? func f( a: (Void) -> Void...) { } ^~~~~~ () <stdin>:2:3: error: extra arguments at positions #2, #2 in call f {} _: {} ^ <stdin>:1:6: note: 'f(a:)' declared here func f( a: (Void) -> Void...) { } ^func f(xx aa: String, xx bb: Int) {} f(xx: 1)<stdin>:2:3: error: missing argument for parameter 'xx' in call f(xx: 1) ^ xx: <#String#>, <stdin>:1:6: note: 'f(xx:xx:)' declared here func f(xx aa: String, xx bb: Int) {} ^func f(_ aa: String, _ bb: Int, cc: Int = 0) {} f(1)<stdin>:2:4: error: missing argument for parameter #2 in call f(1) ^ , <#Int#> <stdin>:1:6: note: 'f(_:_:cc:)' declared here func f(_ aa: String, _ bb: Int, cc: Int = 0) {} ^ <stdin>:2:3: error: cannot convert value of type 'Int' to expected argument type 'String' f(1) ^func f(aa: String = "", bb: Int) {} f(aa: 1)<stdin>:2:3: error: missing argument for parameter 'aa' in call f(aa: 1) ^ aa: <#String#>, <stdin>:1:6: note: 'f(aa:bb:)' declared here func f(aa: String = "", bb: Int) {} ^<stdin>:2:8: error: missing argument for parameter 'bb' in call f(aa: 1) ^ , bb: <#Int#> <stdin>:1:6: note: 'f(aa:bb:)' declared here func f(aa: String = "", bb: Int) {} ^<stdin>:2:3: error: missing argument for parameter 'aa' in call f(aa: 1) ^ aa: <#String#>, <stdin>:1:6: note: 'f(aa:bb:)' declared here func f(aa: String = "", bb: Int) {} ^func f(a: Int, b: Int, c: Int, d: Int) {} func f(a: Int, b: String, x: String, y: String) {} f(a: 0, b: 0, x: 0, y: 0)<stdin>:4:12: error: cannot convert value of type 'Int' to expected argument type 'String' f(a: 0, b: 0, x: 0, y: 0) ^ <stdin>:4:18: error: cannot convert value of type 'Int' to expected argument type 'String' f(a: 0, b: 0, x: 0, y: 0) ^ <stdin>:4:24: error: cannot convert value of type 'Int' to expected argument type 'String' f(a: 0, b: 0, x: 0, y: 0) ^func f(a: Int, b: Int, c: Int, d: Int) {} func f(a: Int, b: String, x: String, y: String) {} f(a: 0, b: 0, x: 0, y: 0) (edited)---Constraint solving for the expression at [<stdin>:4:1 - line:4:25]--- (disabled disjunction term $T0 bound to decl main.(file).f(a:b:c:d:)@<stdin>:1:6 : (Int, Int, Int, Int) -> () at <stdin>:1:6 [[locator@0x849fea0 [OverloadedDeclRef@<stdin>:4:1]]];) (introducing single enabled disjunction term $T0 bound to decl main.(file).f(a:b:x:y:)@<stdin>:2:6 : (Int, String, String, String) -> () at <stdin>:2:6 [[locator@0x849fea0 [OverloadedDeclRef@<stdin>:4:1]]];) (overload set choice binding $T0 := (Int, String, String, String) -> ()) (common result type for $T0 is ()) ---Initial constraints for the given expression--- (call_expr type='()' location=<stdin>:4:1 range=[<stdin>:4:1 - line:4:25] arg_labels=a:b:x:y: (overloaded_decl_ref_expr type='$T0' location=<stdin>:4:1 range=[<stdin>:4:1 - line:4:1] name=f number_of_decls=2 function_ref=single decls=[ main.(file).f(a:b:c:d:)@<stdin>:1:6, main.(file).f(a:b:x:y:)@<stdin>:2:6]) (tuple_expr type='(a: $T1, b: $T2, x: $T3, y: $T4)' location=<stdin>:4:2 range=[<stdin>:4:2 - line:4:25] names=a,b,x,y (integer_literal_expr type='$T1' location=<stdin>:4:6 range=[<stdin>:4:6 - line:4:6] value=0 builtin_initializer=**NULL** initializer=**NULL**) (integer_literal_expr type='$T2' location=<stdin>:4:12 range=[<stdin>:4:12 - line:4:12] value=0 builtin_initializer=**NULL** initializer=**NULL**) (integer_literal_expr type='$T3' location=<stdin>:4:18 range=[<stdin>:4:18 - line:4:18] value=0 builtin_initializer=**NULL** initializer=**NULL**) (integer_literal_expr type='$T4' location=<stdin>:4:24 range=[<stdin>:4:24 - line:4:24] value=0 builtin_initializer=**NULL** initializer=**NULL**))) Score: 0 0 0 0 0 0 0 0 0 0 0 0 Type Variables: $T0 [lvalue allowed] [noescape allowed] as (Int, String, String, String) -> () @ locator@0x849fea0 [OverloadedDeclRef@<stdin>:4:1] $T1 [noescape allowed] literal=3 bindings={(subtypes of) (default from ExpressibleByIntegerLiteral) Int} @ locator@0 (edited)func f(a: Int, b: String, x: String, y: String) {} func f(a: Int, b: Int, c: Int, d: Int) {} f(a: 0, b: 0, x: 0, y: 0)---Constraint solving for the expression at [<stdin>:4:1 - line:4:25]--- (disabled disjunction term $T0 bound to decl main.(file).f(a:b:c:d:)@<stdin>:2:6 : (Int, Int, Int, Int) -> () at <stdin>:2:6 [[locator@0x9279ea0 [OverloadedDeclRef@<stdin>:4:1]]];) (introducing single enabled disjunction term $T0 bound to decl main.(file).f(a:b:x:y:)@<stdin>:1:6 : (Int, String, String, String) -> () at <stdin>:1:6 [[locator@0x9279ea0 [OverloadedDeclRef@<stdin>:4:1]]];) (overload set choice binding $T0 := (Int, String, String, String) -> ()) (common result type for $T0 is ()) ---Initial constraints for the given expression--- (call_expr type='()' location=<stdin>:4:1 range=[<stdin>:4:1 - line:4:25] arg_labels=a:b:x:y: (overloaded_decl_ref_expr type='$T0' location=<stdin>:4:1 range=[<stdin>:4:1 - line:4:1] name=f number_of_decls=2 function_ref=single decls=[ main.(file).f(a:b:x:y:)@<stdin>:1:6, main.(file).f(a:b:c:d:)@<stdin>:2:6]) (tuple_expr type='(a: $T1, b: $T2, x: $T3, y: $T4)' location=<stdin>:4:2 range=[<stdin>:4:2 - line:4:25] names=a,b,x,y (integer_literal_expr type='$T1' location=<stdin>:4:6 range=[<stdin>:4:6 - line:4:6] value=0 builtin_initializer=**NULL** initializer=**NULL**) (integer_literal_expr type='$T2' location=<stdin>:4:12 range=[<stdin>:4:12 - line:4:12] value=0 builtin_initializer=**NULL** initializer=**NULL**) (integer_literal_expr type='$T3' location=<stdin>:4:18 range=[<stdin>:4:18 - line:4:18] value=0 builtin_initializer=**NULL** initializer=**NULL**) (integer_literal_expr type='$T4' location=<stdin>:4:24 range=[<stdin>:4:24 - line:4:24] value=0 builtin_initializer=**NULL** initializer=**NULL**))) Score: 0 0 0 0 0 0 0 0 0 0 0 0 Type Variables: $T0 [lvalue allowed] [noescape allowed] as (Int, String, String, String) -> () @ locator@0x9279ea0 [OverloadedDeclRef@<stdin>:4:1] $T1 [noescape allowed] literal=3 bindings={(subtypes of) (default from ExpressibleByIntegerLiteral) Int} @ locator@0commit 98522b0b7100a5e3657fd340214429c198039f0a (HEAD -> master, origin/master, origin/HEAD) Merge: b148e241867 439c1481bea Author: Hamish Knight <hamish_knight@apple.com> Date: Thu May 28 18:41:25 2020 -0700 Merge pull request #32067 from hamishknight/a-delayed-filingfunc foo<X>(_ aa: X, _ bb: Int) -> X { aa } foo((1, 2)) [1] これは第二引数が不足している [2] これは丸括弧が余計(tuple splat fixすべき) (edited)func foo<X, Y>(_ aa: X, _ bb: Y) -> X { aa } foo((1, 2)) [1] これは第二引数が不足している [2] これは丸括弧が余計(tuple splat fixすべき) (edited)func foo<X>(_ aa: X, _ bb: Int, _ cc: Int) -> X { aa } foo((1, 2, 3))error: failed to launch REPL process: process exited with status -1 (attach failed (Not allowed to attach to process. Look in the console messages (Console.app), near the debugserver entries when the attached failed. The subsystem that denied the attach permission will likely have logged an informative message about why it was denied.))template <class T> T add(T a, T b) { return a + b; } public func testAdd(x: Int32) -> Int32 { return add(x, x) } template <class T> T passThrough(T value) { return value; } public func testPassThroughAny(x: Any) -> Any { return passThrough(x) }An asynchronous handler behaves externally like a synchronous function, but internally it is handled like an asynchronous function, meaning that it can execute operations with suspension points such as calling other async functions. The body of the function is executed just as if it and its caller were async functions, except that the caller is resumed when the callee reaches its first suspension point rather than only when the callee exits.c++ if (argIdx == 0) { for (auto word : camel_case::getWords(selectorPiece)) { if (word == "did" || word == "Did") return true; } continue; }c++ static bool isCompletionHandlerParamName(StringRef paramName) { return paramName == "completionHandler" || paramName == "completion" || paramName == "withCompletionHandler"; } parser.add_argument('--enable-experimental-concurrency', action='store_true', help='Enable experimental concurrency model.')func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTaskURLSession.shared.dataTask(with: url) { (result: Result<(response: URLResponse, data: Data), Error>)extension URLSession { public func dataTaskPublisher(for url: URL) -> URLSession.DataTaskPublisher public func dataTaskPublisher(for request: URLRequest) -> URLSession.DataTaskPublisher public struct DataTaskPublisher : Publisher { public typealias Output = (data: Data, response: URLResponse) public typealias Failure = URLError } }Future 使って並列化するコードはこんな感じになるかと。 let a = Future { await foo() } let b = Future { await bar() } let sum = await a.get() + b.get()get で値を取り出せるのが違うところでしょうか。actor もマージされてるの、プロポーザル出る前からめちゃくちゃ動いてますね・・・。actor の使い方の参考になりそう。 https://github.com/DougGregor/swift/blob/099de9d3e589bc120717466a52cc42e483c016c0/test/Concurrency/actor_isolation.swift // Accesses on other actors can only reference immutable data or // call asychronous methods _ = otherActor.immutable // okay _ = otherActor.synchronous() // expected-error{{actor-isolated instance method 'synchronous()' can only be referenced on 'self'}} _ = await otherActor.asynchronous() _ = otherActor.text[0] // expected-error{{actor-isolated property 'text' can only be referenced on 'self'}}async/await は actor 関係ないかと。async/awaitasync/await は前座的な感じ。async/await は↓に切り出されてる。 https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619beginAsync の body って @escaping じゃなくていいんですっけ? func beginAsync(_ body: () async throws -> Void) rethrows -> Void
https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619 (edited)@escaping は非 async なクロージャにしかついてないし、そういう構文っぽい。beginAsync の throws と rethrows 要らないってずっと言ってたけど、 @asyncHandler では throws 禁止されてていい感じ。@asyncHandler が挿入されないのは inout 相当だから? - (void)refrigerator:(id)fridge didGetFilledWithIntegers:(NSInteger *)items count:(NSInteger)count;async/await と actor 周りの話をまとめました。 https://zenn.dev/koher/articles/swift6-concurrency
2suspendAsync 相当のものがないと作れないと思います。suspendAsync が Promise を作るのに相当するので。beginAsync については @asyncHandler になるようですが、 suspendAsync がどうなるかはこの前調べた時点ではまだ不明だったと思います。async/await を試せるようにオプションをつけて実行するようにしました。 https://swiftfiddle.com/ibz6zkexrbcmdd3zs2xz3oamkm ホントはネットワークリクエストとかそれっぽいサンプルを書きたかったけど書けないのでしょうがない。import Dispatch func suspendAsync<T>( _ body: (_ continuation: @escaping (T) -> ()) -> () ) async -> T { let semaphore = DispatchSemaphore(value: 0) var result: T! body { value in result = value semaphore.signal() } semaphore.wait() return result } extension DispatchQueue { func asyncAfter(deadline: DispatchTime) async { await suspendAsync { continuation in asyncAfter(deadline: deadline) { continuation(()) } } } } @asyncHandler func main() { print("A") await DispatchQueue.global().asyncAfter(deadline: .now() + 1) print("B") await DispatchQueue.global().asyncAfter(deadline: .now() + 1) print("C") } main()suspendAsync を作ってみました。async/await を使ったコードを書いてみるくらいの役にしか立ちません。Future で包むというのがプロポーザルに書かれてたと思います。let a = Future { await foo() } let b = Future { await bar() } let sum = await a.get() + b.get()@asyncHandler になるかと。await 忘れないのいいですよね。@IBAction @asyncHandler func onButtonPressed(_ sender: UIButton) { await sendValue(value, to: url) }beginAsync だったので、 @IBAction func onButtonPressed(_ sender: UIButton) { beginAsync { await sendValue(value, to: url) } } になるはずだったかと思います。async 忘れで待たずに抜けちゃいますし、 Kotlin の suspend は Swift の async と同じなんですが、 await 相当のものがないのでどこで await してるかぱっと見でわかんないんですよね。@asyncHandler は caller 側は待たずに抜けるんじゃないでしょうか。@IBAction はメインスレッドをブロックしたくないので caller 側を待たせたくないので。suspendAsync がなんちゃってで同期だからじゃないでしょうか?() の conformance が入った件let input = "1000000000000" let inputs = input.split(separator: "\n").map { Int($0)! } for i in inputs { var answers: Set<Int> = [] for n in 1...(Int(ceil(sqrt(Double(i))))) { if i % n == 0 { answers.insert(n) } } let i2 = i let b = answers for n in b { if i2 % n == 0 { answers.insert(i2 / n) } } let sorted = answers.sorted() for n in sorted { print(n) } }let input = readLine()! //let input = "720" let inputs = input.split(separator: "\n") for input in inputs { var answers: Set<Int> = [] let i = Int(input)! for n in 1...(Int(ceil(sqrt(Double(i))))) { if i % n == 0 { answers.insert(n) answers.insert(i / n) } } let sorted = answers.sorted() for n in sorted { print(n) } } (edited)quotientAndRemainder 無駄がない.map { [$0, n/$0] }.flatMap { $0 } (edited)trueを返す -@inlinable あるなしで実行時間にどのくらい影響あるものなんですかね? (edited)print((a: 1, b: 2) == (b: 1, a: 2)) // true (edited)-driver-print-graphvizif buildParameters.useExplicitModuleBuild {struct MyError1: Error {} struct MyError2: Error {} func throwError() throws { throw MyError1() } do { try throwError() } catch let error { switch error { case is MyError1: print("MyError1") case is MyError2: print("MyError2") default: print("other type") } } (edited)pure)、みたいなことは言えるというようなアプローチで同期もasync letできてしまうほうが自然か(?) (edited)async let dinner = { cookDinner() }
https://github.com/ktoso/swift-evolution/blob/wip-tasklocals/proposals/nnnn-task-locals.md#binding-values-for-the-duration-of-a-child-task (edited) // Wait for all of the chopping to complete, collecting the veggies into // the result array in whatever order they're ready. while let choppedVeggie = try await group.next() { choppedVeggies.append(choppedVeggie) }
https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md#task-groups-and-child-tasks (edited)struct S { func f( _ f1: () throws -> (), _ f2: () throws -> () ) rethrows -> () { } } S().f({ }, { })func a() -> some View ってやるときに @VIewBuilder つける (edited)func f(_: Never) -> Int {}func f(a: Never) -> Int {} (edited)struct Container<T> { func map<T, U>(_ transformer: (T) -> U) -> Container<U> { return .init() } } let n = Container<Never>() let u: Container<Int> = n.map { _ in } (edited)<stdin>:6:25: error: cannot find 'c' in scope let u: Container<Int> = c.map { _ in } ^<stdin>:6:31: error: cannot convert value of type '()' to closure result type 'Int' let u: Container<Int> = n.map { _ in } ^~~~~~~~ <stdin>:6:33: error: unable to infer type of a closure parameter '_' in the current context let u: Container<Int> = n.map { _ in } ^enum Command: Codable { case load(String) case store(key: String, Int) } would encoded to { "load": { "_0": "MyKey" } } and { "store": { "key": "MyKey", "_1": 42 } }Either< Int, Either< String, Int > > (edited)let dictionary: [String: Int] = .init { [ "a": 2, "b": 3, ] if isFoo { ["c": 5] } }enum Command: Codable { case load(key: String) case store(key: String, value: Int) } would be encoded to { "load": { "key": "MyKey" } } and { "store": { "key": "MyKey", "value": 42 } }type member must not be named 'Type', since it would conflict with the 'foo.Type' expression 専用のエラーメッセージあるわ
1Double.description の実装がめっちゃ凝ってたDouble.description は丸めた文字列作ってるんだろう?という話から。 $ swift Welcome to Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28). Type :help for assistance. 1> 0.1 $R0: Double = 0.10000000000000001 2> print(0.1) 0.1 3> print(0.1 + 0.2) 0.30000000000000004Float80サポートと共にFloatingPointの文字列化をSwiftDtoaに置き換えようとしてやめたことを思い出した。 https://github.com/jpsim/Yams/pull/151description implementation This replaces the current implementation of description anddebugDescription for the standard floating-point types with a new form...
* Always Accurate. Converting the decimal form back to binary (using an accurate algorithm such as Clinger's) will always yield exactly the original binary value. For the IEEE 754 formats, the round-trip will produce exactly the same bit pattern in memory. This is an essential requirement for JSON serialization, debugging, and logging.0.1 に丸められても 0.1 というリテラルから元の値が復元されるなら問題ないのかな?Float80のテストを通そうとすると、標準の手段だとダメだったからSwiftDtoaを使おうとしたと記憶。Float80のテストを通そうとすると、標準の手段だとダメだったからSwiftDtoaを使おうとしたと記憶。 $ swift Welcome to Apple Swift version 5.4.2 (swiftlang-1205.0.28.2 clang-1205.0.19.57). Type :help for assistance. 1> 0.1 $R0: Double = 0.10000000000000001 2> print(0.1) 0.1 3> 0.10000000000000001 $R1: Double = 0.10000000000000001 4> print(0.10000000000000001) 0.10.10000000000000001 を2進表現した時の値は 十進でいえば 0.10000000000000001 のほうが 0.1 より近いんじゃあないんか。 (edited)
1#define COMPATIBILITY_OVERRIDE_SECTION_NAME_swiftRuntime "__swift54_hooks" #define COMPATIBILITY_OVERRIDE_SECTION_NAME_swift_Concurrency "__s_async_hook"$ git diff swift-5.3-RELEASE swift-5.4-RELEASE -- include/swift/Runtime/RuntimeFunctions.def[omochi@omochi-iMacPro swift (main=)]$ git diff swift-5.3-RELEASE swift-5.4-RELEASE -- stdlib/public/CompatibilityOverride/CompatibilityOverrideRuntime.def [omochi@omochi-iMacPro swift (main=)]$ git diff swift-5.2-RELEASE swift-5.3-RELEASE -- stdlib/public/CompatibilityOverride/CompatibilityOverrideRuntime.def [omochi@omochi-iMacPro swift (main=)]$ git diff swift-5.1-RELEASE swift-5.2-RELEASE -- stdlib/public/CompatibilityOverride/CompatibilityOverrideRuntime.def [omochi@omochi-iMacPro swift (main=)]$ git diff swift-5.0-RELEASE swift-5.1-RELEASE -- stdlib/public/CompatibilityOverride/CompatibilityOverrideRuntime.def [omochi@omochi-iMacPro swift (main=)]$ git diff swift-4.2-RELEASE swift-5.0-RELEASE -- stdlib/public/CompatibilityOverride/CompatibilityOverrideRuntime.def [omochi@omochi-iMacPro swift (main=)]$ git diff swift-4.2-RELEASE [DRELEASE swift-5.0-RELEASE -- stdlib/public/CompatibilityOverride/CompatibilityOverrideRuntime.def [omochi@omochi-iMacPro swift (main=)]$ git diff swift-4.1-RELEASE swift-4.2-RELEASE -- stdlib/public/CompatibilityOverride/CompatibilityOverrideRuntime.def [omochi@omochi-iMacPro swift (main=)]$ git diff swift-4.0-RELEASE swift-4.2-RELEASE -- stdlib/public/CompatibilityOverride/CompatibilityOverrideRuntime.def [omochi@omochi-iMacPro swift (main=)]$ git diff swift-3.0-RELEASE swift-4.2-RELEASE -- stdlib/public/CompatibilityOverride/CompatibilityOverrideRuntime.def [omochi@omochi-iMacPro swift (main=)]$ git diff swift-3.0-RELEASE swift-5.0-RELEASE -- stdlib/public/CompatibilityOverride/CompatibilityOverrideRuntime.defstdlib/public/CompatibilityOverride/CompatibilityOverride.def っぽいswift/stdlib/public/runtime/CompatibilityOverride.def-OVERRIDE_METADATALOOKUP(getTypeByMangledName, TypeInfo, , SWIFT_CC(swift), swift::, +OVERRIDE_METADATALOOKUP(getTypeByMangledName, TypeLookupErrorOr<TypeInfo>, , SWIFT_CC(swift), swift::, (MetadataRequest request, StringRef typeName, const void * const *arguments,git show swift-5.4-RELEASE:stdlib/public/runtime/CompatibilityOverride.def でタグ時点のファイルを抽出してdiff取りました[omochi@omochi-iMacPro swift (main=)]$ git diff swift-5.4-RELEASE:stdlib/public/runtime/CompatibilityOverride.def swift-5.5-RELEASE:stdlib/public/CompatibilityOverride/CompatibilityOverrideRuntime.def diff --git a/stdlib/public/runtime/CompatibilityOverride.def b/stdlib/public/CompatibilityOverride/CompatibilityOverrideRuntime.def index 1489ee07e1e..3c265c1e335 100644 --- a/stdlib/public/runtime/CompatibilityOverride.def +++ b/stdlib/public/CompatibilityOverride/CompatibilityOverrideRuntime.def @@ -1,4 +1,4 @@ -//===--- CompatibilityOverrides.def - Compatibility Overrides Database -*- C++ -*-===// +//===--- CompatibilityOverridesRuntime.def - Overrides Database -*- C++ -*-===// // // This source file is part of the Swift.org open source project // @@ -15,12 +15,14 @@ // //===----------------------------------------------------------------------===// -/// #define OVERRIDE(name, ret, attrs, namespace, typedArgs, namedArgs) +/// #define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) /// Provides information about an overridable function. /// - name is the name of the function, without any leading swift_ or /// namespace. /// - ret is the return type of the function. /// - attrs is the attributes, if any, applied to the function definition. +/// - ccAttrs is the calling convention attributes, if any, applied to the +/// function definition and corresponding typedefs /// - namespace is the namespace, if any, the function is in, including a /// trailing :: /// - typedArgs is the argument list, including types, surrounded by @@ -34,8 +36,10 @@ /// and OVERRIDE_KEYPATH to get only those entries. // NOTE: this file is used to build the definition of OverrideSection in -// CompatibilityOverride.cpp, which is part of the ABI. Do not move or remove entries -// in this file after ABI stability. Additional entries can be added to the end. +// CompatibilityOverride.cpp, which is part of the ABI. Moving or removing +// entries in this file will break the ABI. Additional entries can be added to +// the end. ABI breaks or version-specific changes can be accommodated by +// changing the name of the override section in that file. #ifdef OVERRIDE # define OVERRIDE_METADATALOOKUP OVERRIDEgit diff swift-5.1-RELEASE swift-5.2-RELEASE -- stdlib/public/runtime/CompatibilityOverride.def git diff swift-5.1-RELEASE swift-5.2-RELEASE -- stdlib/public/runtime/CompatibilityOverride.def git diff swift-5.2-RELEASE swift-5.3-RELEASE -- stdlib/public/runtime/CompatibilityOverride.def このへんもdiffゼロだけどセクション名更新されてますね-OVERRIDE_METADATALOOKUP(getTypeByMangledNode, TypeInfo, , SWIFT_CC(swift), swift::, +OVERRIDE_METADATALOOKUP(getTypeByMangledNode, TypeLookupErrorOr<TypeInfo>, , SWIFT_CC(swift), swift::, 5.4のこれは本当に返り値が変わっただけかOVERRIDE_METADATALOOKUP(getTypeByMangledNode, TypeLookupErrorOr<TypeInfo>, , SWIFT_CC(swift), swift::, (MetadataRequest request, Demangler &demangler, Demangle::NodePointer node, const void * const *arguments, SubstGenericParameterFn substGenericParam, SubstDependentWitnessTableFn substWitnessTable), (request, demangler, node, arguments, substGenericParam, substWitnessTable)) OVERRIDE_METADATALOOKUP(getTypeByMangledName, TypeLookupErrorOr<TypeInfo>, , SWIFT_CC(swift), swift::, (MetadataRequest request, StringRef typeName, const void * const *arguments, SubstGenericParameterFn substGenericParam, SubstDependentWitnessTableFn substWitnessTable), (request, typeName, arguments, substGenericParam, substWitnessTable))
1
1main.swift がある」に依存してビルドが制御されてるのがキモいという問題が解決するのか@Section(title: "") にするとクラッシュした Documentation/MyPackage.docc/// Converts: /// %extract = struct_extract %src : $TypeWithSingleOwnershipValue /// %copy = copy_value %extract : $OwnershipValue /// To: /// %copy = copy_value %src : $TypeWithSingleOwnershipValue /// (%extracted,...) = destructure %copy : $OwnershipValue (edited)/// For types with a single reference member, converts /// src -> struct_extract -> copy /// into /// src -> copy -> destructure // Delete a dead forwarded value before sinking to avoid this pattern: // %outerVal = destructure_struct %def // destroy %outerVal <= delete this destroy now // destroy %def <= so we don't delete this one later/// Because this algorithm rewrites copies and destroys without attempting to /// balance the retain count, it is only sound when SIL is in ownership-SSA /// form.// main sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = metatype $@thick Cat.Type // user: %4 // function_ref Cat.__allocating_init() %3 = function_ref @$s4test3CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %4 %4 = apply %3(%2) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %22, %8, %5 debug_value %4 : $Cat, let, name "mike" // id: %5 %6 = alloc_box ${ var @sil_unowned Cat }, let, name "tama" // users: %21, %7 %7 = project_box %6 : ${ var @sil_unowned Cat }, 0 // users: %15, %12 %8 = begin_borrow %4 : $Cat // users: %14, %9 %9 = copy_value %8 : $Cat // users: %13, %10 %10 = ref_to_unowned %9 : $Cat to $@sil_unowned Cat // user: %11 %11 = copy_value %10 : $@sil_unowned Cat // user: %12 store %11 to [init] %7 : $*@sil_unowned Cat // id: %12 destroy_value %9 : $Cat // id: %13 end_borrow %8 : $Cat // id: %14 %15 = load_borrow %7 : $*@sil_unowned Cat // users: %17, %16 %16 = strong_copy_unowned_value %15 : $@sil_unowned Cat // users: %20, %19, %18 end_borrow %15 : $@sil_unowned Cat // id: %17 %18 = class_method %16 : $Cat, #Cat.meow : (Cat) -> () -> (), $@convention(method) (@guaranteed Cat) -> () // user: %19 %19 = apply %18(%16) : $@convention(method) (@guaranteed Cat) -> () destroy_value %16 : $Cat // id: %20 destroy_value %6 : ${ var @sil_unowned Cat } // id: %21 destroy_value %4 : $Cat // id: %22 %23 = integer_literal $Builtin.Int32, 0 // user: %24 %24 = struct $Int32 (%23 : $Builtin.Int32) // user: %25 return %24 : $Int32 // id: %25 } // end sil function 'main'
1
1
(edited)
1${product_name}_${module_name}.${class_name}
1a.components(separatedBy: "_") ですかね?productname_modulename が入ってそうだからそれでもいけますねa.components(separatedBy: "_") ですかね? このようにバッククォート3つ
このようにバッククォート1つ
@mt.hodaka こうやるといいですよ waiwai-swiftc チャンネル
5.members.members w (edited)_InternalSwiftSyntaxParser.xcframework が配られてる https://github.com/apple/swift-syntax/releases/tag/0.50600.1 (edited).1 ブランチを使うと指定してくれてありそうResult<T, E> -> T | Eってことかexport TOOLCHAINS=org.swift.57202205181afunc foo(cat: Cat) -> Void { ... } func consumeFoo(_ f: (Animal) -> Void) { ... } consumeFoo(foo) (edited)func foo(f: (Cat) -> Void) { ... } func consumeFoo(_ f: ((Animal) -> Void) -> Void) { ... } consumeFoo(foo) (edited)Observable<T>.subscribe(observer: (T) -> Void)Observable<Int> is Observable<Int?>
2@objcがcovariantみたいな話は聞いたことある気がするA function or closure that throws can effectively return a value of any type that conforms to the Error protocol. If the function is called from a different concurrency domain, the thrown value can be passed across it. To close this safety hole, we alter the definition of the Error protocol to require that all error types conform to Sendable:
https://github.com/apple/swift-evolution/blob/main/proposals/0302-concurrent-value-and-concurrent-closures.md#thrown-errors// このように Animal を継承した Cat, Dog があるときに class Animal { ... } class Cat: Animal { ... } class Dog: Animal { ... }
// Covariant final class List<T> { // 戻り値の位置で T を利用 → Covariant get(at index: Int) -> T } let cats: List<Cat> = ... let animals: List<Animal> = cats // ✅ OK: なぜなら // ↓取り出された Cat インスタンスは Animal なので問題ない let animal: Animal = animals.get(at: 0)
// Contravariant final class List<T> { // 引数の位置で T を利用 → Contravariant set(_ value: T, at index: Int) } let cats: List<Cat> = ... let animals: List<Animal> = cats // ⛔ NG: なぜなら // ↓ animals === cats に Dog インスタンスを set できて破綻 animals.set(Dog(), at: 0)// Contravariant × Contravariant → Covariant final class List<T> { // 引数に渡すクロージャの引数の位置で T を利用 // Contravariant × Contravariant → Covariant func map<U>(transform: (T) -> U) -> List<U> } let cats: List<Cat> = ... let animals: List<Animal> = cats // ✅ OK: なぜなら↓ // ↓ map に渡されたクロージャが // 引数で受け取った Animal の任意のメンバにアクセスしても、 // 実際に渡されるのは Cat なので問題ない let noses: List<Nose> = animals.map(\.nose)// Contravariant let animals: List<Animal> = ... let cats: List<Cat> = animals // ✅ OK // ↓ animals に Cat が set されても問題ない cats.set(Cat(...), at: 0) // Covariant let animals: List<Animal> = ... let cats: List<Cat> = animals // ⛔ NG // ↓任意の Animal が返って来得るので破綻 let cat: Cat = cats.get(at: 0)let n: Int = 42 let intType: Int.Type = n.dynamicTypen.dynamicType -> type(of: n) (edited)protocol P {} func makeP() -> some P { fatalError() }protocol P {} func makeP() -> some P { fatalError() } <stdin>:3:5: error: return type of global function 'makeP()' requires that 'Never' conform to 'P' fatalError() ^ <stdin>:2:17: note: opaque return type declared here func makeP() -> some P { ^~~~~~protocol P {} func makeP() -> some P { return fatalError() }protocol P {} func makeP() -> some P { return fatalError() } <stdin>:3:12: error: return type of global function 'makeP()' requires that 'Never' conform to 'P' return fatalError() ^ <stdin>:2:17: note: opaque return type declared here func makeP() -> some P { ^~~~~~protocol P {} extension Never: P {} func makeP() -> some P { return fatalError() }protocol P {} extension Never: P {} func makeP() -> some P { return fatalError() } <stdin>:4:5: warning: will never be executed return fatalError() ^ <stdin>:4:12: note: a call to a never-returning function return fatalError() ^
1
4
2print(type(of: t)) みたいなのされたらだめなのか。protocol P {} extension P { func f() -> Self { self } }protocol P {} extension P { func f() -> Self { self } } protocol P {} extension P { func f() -> some P { self } }protocol P {} extension P { func f() -> some P { self } } func f<T>() -> any Sequence<T> (edited)func f<T>() -> any Sequence<T> (edited)__swift_instantiateConcreteTypeFromMangledName の中で呼ばれている swift_getTypeByMangledNameInContext が some type を組み合わせて返すような状況で何が起こっているか調べる ↓の発表で若干見せているけど踏み込んでいない https://speakerdeck.com/omochi/swift6falseprotocol
1
1"-Xfrontend", "-disable-availability-checking"@_spi(PatternConverter) public func renderAsBuilderDSL( ast: Any, ...@_spi(PatternConverter) import _StringProcessing@testable @_spi(PatternConverter) import _StringProcessing ...public struct RegexSemanticLevel: Hashable { internal enum Representation { case graphemeCluster case unicodeScalar }_RegexParser.parse アンスコ付いててダサいなぁ.some(.some(.some(.none)))みたいなこと?Regex<(SubString????????)>Referenceので参照する必要がある)ってのあった気がします/<(?P<tag>[A-Z][A-Z0-9]*)\b[^>]*>.*?<\/(?P=tag)>//<([A-Z][A-Z0-9]*)\b[^>]*>.*?<\/\1>/ "<" Capture { Regex { ("A"..."Z") ZeroOrMore { CharacterClass( ("A"..."Z"), ("0"..."9") ) } } } Anchor.wordBoundary ZeroOrMore(.anyOf(">").inverted) ">" ZeroOrMore(.reluctant, .any) "</" /* TOOD: backreferences */ ">" }/(?(?=regex)then|else)//<([A-Z][A-Z0-9]*)\b[^>]*>.*?<\/\2>/Cannot parse regular expression: no capture numbered 2 (edited)/<(?P<tag>[A-Z][A-Z0-9]*)\b[^>]*>.*?<\/(?P=tab)>/ ^ コンパイルエラー Cannot parse regular expression: no capture named 'tab' (edited)-enable-bare-slash-regexlet re = /Hello, (\w+)?/let re = /Hello, (\w+)?/ <stdin>:1:19: error: expected pattern let re = /Hello, (\w+)?/ ^ <stdin>:1:23: error: consecutive statements on a line must be separated by ';' let re = /Hello, (\w+)?/ ^ ; <stdin>:1:23: error: expected expression let re = /Hello, (\w+)?/ ^ <stdin>:1:10: error: '/' is not a prefix unary operator let re = /Hello, (\w+)?/ ^ <stdin>:1:11: error: cannot find 'Hello' in scope let re = /Hello, (\w+)?/ ^~~~~let re = /Hello, (\w+)?/ print(type(of: re).self) (edited)let re = /Hello, (\w+)?/ print(type(of: re).self) (edited)Regex<(Substring, Optional<Substring>)> (edited)let re = /Hello, (a(\w+)?)?/ print(type(of: re))let re = /Hello, (a(\w+)?)?/ print(type(of: re)) Regex<(Substring, Optional<Substring>, Optional<Substring>)>import RegexBuilder let re = Regex { "Hello, " Optionally { Capture { "a" Optionally { Capture { OneOrMore(.word) } } } } } print(type(of: re))import Foundation import RegexBuilder import _StringProcessing (edited) import Foundation import RegexBuilder import _StringProcessing let re = Regex { "Hello, " Optionally { Capture { "a" Optionally { Capture { OneOrMore(.word) } } } } } print(type(of: re))import RegexBuilder let re = Regex { "Hello, " Optionally { Capture { "a" Optionally { Capture { OneOrMore(.word) } } } } } print(type(of: re)) import Foundation import RegexBuilder import _StringProcessing let re = Regex { "Hello, " Optionally { Capture { "a" Optionally { Capture { OneOrMore(.word) } } } } } print(type(of: re)) import RegexBuilder var aaa = Regex { "Hello, " Optionally { Optionally { Capture { OneOrMore(.word) } } } } print(type(of: aaa))import RegexBuilder var aaa = Regex { "Hello, " Optionally { Optionally { Capture { OneOrMore(.word) } } } } print(type(of: aaa)) Regex<(Substring, Optional<Optional<Substring>>)>
1foo[keyPath: \.bar]print(\Int.self == \Int.self.self)struct Foo { struct Bar { var baz: Int { 42 } } var bar: Bar?? { Bar() } } print(\Foo.bar??.baz)struct Foo { struct Bar { var baz: Int { 42 } } var bar: Bar?? { Bar() } } print(\Foo.bar??.baz) Swift.KeyPath<main.Foo, Swift.Optional<Swift.Int>>struct Foo { struct Bar { var baz: Int? { 42 } } var bar: Bar? { Bar() } } print(\Foo.bar?.baz?.description)struct Foo { struct Bar { var baz: Int? { 42 } } var bar: Bar? { Bar() } } print(\Foo.bar?.baz?.description) Swift.KeyPath<main.Foo, Swift.Optional<Swift.String>>struct S<T> { subscript(_ v: T) -> T { fatalError() } } func f<X: Hashable>(x: X) -> AnyKeyPath { \S.[x] } (edited)struct S<T> { subscript(_ v: T) -> T { fatalError() } } func f<X: Hashable>(x: X) -> AnyKeyPath { \S.[x] } (edited).map(\.id) より .map { $0.id }KeyPath の高速化に取り組んでいるらしく (Forums より) て,ランタイム側の変更だけでも割と速くなるみたいですね. https://github.com/apple/swift/pull/60758 (edited)
2
3
2
1
1
4string & { この時点でもう草まみれString & { ならまぁ、良くはないがわからんでもない& での合成は含まれるプロパティをマージするってことだから。HList 先輩を持ってくれば…… length とかが出てくる keyOfはランタイムでの動作で、型レベルにも keyOf という型レベル計算が定義されていて、その2つの違いってことかな?length はランタイムでメンバーのプロパティーが取れる的なことかと思ったけどそうでもないのか
1
7
1@ Publish とCombine、そういう関係だったのか。@Published はそのまんまで、巻き込まれ再描画や同値再描画をやめればよかったのでは感がするのですが@Publised 書くのが幸せか、 @DefaultObservable 書くのが幸せか@StateObject や @ObservedObject が消える話、 @StateObject var model: Model のときに、 $model.foo で Binding 取ってるのできなくならない?@StateObject や @ObservedObject が消える話、 @StateObject var model: Model のときに、 $model.foo で Binding 取ってるのできなくならない? presenter.trust += Point(334)@Attribute は結局マクロで全部できるっちゃできますからね。最高に読みにくくなるけど。@Attribute に整理するのが設計の勘所かしら。
1all @*Object property wrappers will be able to be used as their non-object counterparts - i.e. where you used @StateObject before just @State etc. ただ、その下で、なるべくPropertyWrapperをつける作業は消したいようなことも言ってます。 the intent is to allow for when Observable is used developers need to consider fewer potential property wrappers and in the case where no lifetime specialities or bindings are needed and just plain observations are desired, no property wrapper is required. (edited)@StateObject private var viewModel: FooViewModel = .init(...) の代わりに、 FooViewModel が ObservableObject でなく Observable になったら @State private var viewModel: FooViewModel = .init(...) になるんですね。おもしろい。@EnvironmentObject が @Environment になるのはおかしいような・・・。@StateObject は Observable になれば言語的に変更を検出できるようになって @State で値型とまとめて扱えるようになるみたいなことを言いたいんだと思うんですが、 @EnvironmentObject と @Environment の関係って、 @StateObject と @State の関係とはちょっと違うと思うんですよね。@ObservedObject は消えて、単に let で渡して、 @State 持ってる View から伝播する感じになるのかなぁ。After taking the motivating use cases surfaced in this pitch thread and implementing them as macros, I'm confident that macros can fully subsume type wrappers while providing more flexibility to library authors.
https://forums.swift.org/t/pitch-type-wrappers/60019/45 (edited)Holly and I have been collaborating on some updates to this for the use of macros.
https://forums.swift.org/t/pitch-observation/62051/105 (edited)
1
1
2[1 + 2 * 3] (edited)1 + (2 * 3)
11+2+3 = 6, 1*2*3 = 6 なので+と*は同じoperator precedence 文を読み取らないといけないから、パーサステージではできない。
1/aaa[0-1*/ ←こういうの) コンパイルエラー出てくれるんでしたっけ。RegexのためのLexerあったら面倒見てくれそうな感じがするけどimport TypeScriptASTimport TypeScriptAST /// lexNumber: /// integer_literal ::= [0-9][0-9_]* /// integer_literal ::= 0x[0-9a-fA-F][0-9a-fA-F_]* /// integer_literal ::= 0o[0-7][0-7_]* /// integer_literal ::= 0b[01][01_]* /// floating_literal ::= [0-9][0-9]_*\.[0-9][0-9_]* /// floating_literal ::= [0-9][0-9]*\.[0-9][0-9_]*[eE][+-]?[0-9][0-9_]* /// floating_literal ::= [0-9][0-9_]*[eE][+-]?[0-9][0-9_]* /// floating_literal ::= 0x[0-9A-Fa-f][0-9A-Fa-f_]* /// (\.[0-9A-Fa-f][0-9A-Fa-f_]*)?[pP][+-]?[0-9][0-9_]* (edited)8*3 + 8 + protocols.count * 8protocol X: class だと16バイトで済むτ_0 とかで消えてるしなぁ$*Shapeの$*は何を意味してるんだろう*はアドレス型、$はSIL上での型につくプレフィックス$s は 「Swiftのシンボル」 全部についてるExistentialSpecialifer.cpp が思ったより行数が少ないな<T> とかany のオーバーヘッドの話、SwiftならDIを型パラインジェクションでやればExistentialのオーバーヘッドないですよね?Specializeされた場合。 protocol DependenciesProtocol { static func a(x: Int) -> Int } final class Foo<Dependencies: DependenciesProtocol> { func b() { let a = Dependencies.a(...) } }any のオーバーヘッドの話、SwiftならDIを型パラインジェクションでやればExistentialのオーバーヘッドないですよね?Specializeされた場合。 protocol DependenciesProtocol { static func a(x: Int) -> Int } final class Foo<Dependencies: DependenciesProtocol> { func b() { let a = Dependencies.a(...) } } any を消すことも。 protocol DependenciesProtocol { func a(x: Int) -> Int } final class Foo<Dependencies: DependenciesProtocol> { let dependencies: Dependencies init(dependencies: Dependencies) { self.dependencies = dependencies } func b() { let a = dependencies.a(...) } } (edited)protocol MyRepository {} class MyRepositoryImpl {} class Container<R1: MyRepository> {} このような構成を考えた場合、Container<MyRepositoryImpl>の宣言と取り回しが必要になり、使う側が具体実装を参照可能な必要が出てきて、これだと例えばframeworkを分離した状態だと、使えない気がしていますprotocol FooRepositoryProtocol { ... } protocol BarRepositoryProtocol { ... } protocol RepositoriesProtocol { associatedtype FooRepository: FooRepositoryProtocol associatedtype BarRepository: BarRepositoryProtocol } @MainActor final class QuxViewState<Repositories: RepositoriesProtocol>: ObservableObject { ... }
// Framework A protocol RepositoryProtocol { static func fetchAll() async throws -> [Foo] } final class Container<Repository: RepositoryProtocol> { ... } // Framework B final class Store<Repository: RepositoryProtocol> { @Published var foos: [Foo.ID: Foo] = [:] func load() async throws { let foos = try await Repository.fetchAll() self.foos = ... } } // App enum Repository: RepositoryProtocol { static func featchAll() async throws -> [Foo] { ... } } let store: Store<Repository> = ...
FooRepository を使う Container1 があったとして、仕様変更になったときに BarRepository も必要になったら、たとえコンストラクタインジェクションしててもコンストラクタ(イニシャライザ)の引数を増やさないといけないですよね? final class Container1 { - init(fooRepository: any FooRespository) { + init(fooRepository: any FooRespository, barRepository: any BarRepository) { そうなると、 Container1 の利用箇所に問題が波及しますし、もし Container2 が Container1 をイニシャライズするような場合、 Container2 のイニシャライザにも影響が出たりしませんか? final class Container2 { - init(fooRepository: any FooRespository) { + init(fooRepository: any FooRespository, barRepository: any BarRepository) { self.fooRepository = fooRepository + self.barRepository = barRepository - self.container1 = Container1(fooRepository: fooRepository) + self.container1 = Container1(fooRepository: fooRepository, barRepository: barRepository) なので、ある程度広めにまとめて多少利用しないものが入っても気にしないようにしており、そうすると(型パラインジェクションする場合でも)DIのための型パラは大抵一つにおさまるので、そこまで型パラが問題になることは多くないのではないかと思います。
(edited)convenience init を作るのは型パラのときに型を埋めた typealias を作るのと同じようなことになりませんか? (edited)class Store { init(r: any MyRepository) } framework Bにおいてはこの実装があるだけで良くなる。class Store<MyRepository: MyRepositoryProtocol> { } の実装がframework Bにあるだけではできないことは何ですか? (edited)FooRepository を使う Container1 があったとして、仕様変更になったときに BarRepository も必要になったら、たとえコンストラクタインジェクションしててもコンストラクタ(イニシャライザ)の引数を増やさないといけないですよね? final class Container1 { - init(fooRepository: any FooRespository) { + init(fooRepository: any FooRespository, barRepository: any BarRepository) { そうなると、 Container1 の利用箇所に問題が波及しますし、もし Container2 が Container1 をイニシャライズするような場合、 Container2 のイニシャライザにも影響が出たりしませんか? final class Container2 { - init(fooRepository: any FooRespository) { + init(fooRepository: any FooRespository, barRepository: any BarRepository) { self.fooRepository = fooRepository + self.barRepository = barRepository - self.container1 = Container1(fooRepository: fooRepository) + self.container1 = Container1(fooRepository: fooRepository, barRepository: barRepository) なので、ある程度広めにまとめて多少利用しないものが入っても気にしないようにしており、そうすると(型パラインジェクションする場合でも)DIのための型パラは大抵一つにおさまるので、そこまで型パラが問題になることは多くないのではないかと思います。
(edited)fatalError になる)デフォルト実装を書くようにしており、そうするとダミーの依存の埋めるのがそんなに大変じゃない印象ですね。 (edited)Environment で渡したものって @StateObject に渡しづらいので、Repositoryとか注入しようとすると結構難しくないですか?ObservableObject 側は Repository 等のプロパティを IUO にしとく感じですか? (edited)Environment を使えば(型パラにせよイニシャライザの引数にせよ)バケツリレーしなくていいのはいいですね。class MyViewModel: ObservableObject { ... class Logic { init(Dependencies) } var logic: Logic! } みたいに別のinitで担保すれば、後から追加があっても大凡カバーできます。やる必要あるケースがどれだけあるかはわからないですがpublic struct URLRoutingClient<Route> { var request: (Route) async throws -> (Data, URLResponse) let decoder: JSONDecoder public init( request: @escaping (Route) async throws -> (Data, URLResponse), decoder: JSONDecoder = .init() ) { self.request = request self.decoder = decoder } live, noop, failingを用途に応じて差し替える public static func live<R: ParserPrinter>( router: R, session: URLSession = .shared, decoder: JSONDecoder = .init() ) -> Self where R.Input == URLRequestData, R.Output == Route { Self.init( request: { route in let request = try router.request(for: route) return try await session.data(for: request) }, decoder: decoder ) } public static let noop = Self.init(request: { _ in try await Task.never() }) public static var failing: Self { Self { let message = """ Failed to respond to route: \(debugPrint($0)) Use '\(Self.self).override' to supply a default response for this route. """ XCTFail(message) throw UnimplementedEndpoint(message: message) } }
3Foo<> には、 直接の Repository と、 UserEditService の型パラメータの Repository と、 ZooEditService の型パラメータの Repository が3回出現しているので、 型パメータとして具体的な依存の実体である DatabaseRepository を 3回書かないといけない。 しかもこれは Repository を利用するコンポーネントが増えるたびに増えていきます。 一般的な動的なDIコンテナだったら、 まず Repository を登録して、その他のそれを利用するサービスは、 自身の依存先を DIコンテナ自体から取り出す事によって構築するので、 「具体的なRepositoryが何であるか」という宣言(コード上の表明) は1箇所で良いはずが、 このアプローチだと自明なはずの事を何度も繰り返して書かないといけない問題がありそうです。 (edited)DummyRepository に変える」というセットアップがしたいとします。 しかし、できない気がします。 共通部分も含めて、テスト用の構成をすべて書きくださないといけないとすると、 「ある一箇所だけスタブに変更する」という意味づけのコードが書けない気がします。
1
1
1let a: Double = (1.0 + 2) + (3 + 4) + (5 + 6) みたいに1つDoubleリテラルにしたらいけたrepeat each だろうが 特別扱いなどはされないですかね https://fxtwitter.com/treastrain/status/1796142350349033730T == (repeat each E) ではない方に吸い込まれてしまうのだけど #わいわいswiftc Quoting treastrain / Tanaka.R (@treastrain) Swift 5.9 の repeat/each where 句でジェネリクスの型パラメータに repeat each なものを指定しても、うまい具合にそっちに処理が流れてくれない… このスクリーンショットの場合だと「Type-A」の方の init 自体を消す他ない……?noasync
3
1protocol P {} protocol P2: P {} protocol Q {} func f(_ v: (any P)...) { print("(any P)...") } func f(_ v: some (P2 & Q)) { print("some (P2 & Q)") } struct S: P2, Q {} f(S())protocol P {} protocol P2: P {} protocol Q {} func f(_ v: (any P)...) { print("(any P)...") } func f(_ v: some (P2 & Q)) { print("some (P2 & Q)") } struct S: P2, Q {} f(S()) (any P)...some (P2 & Q)になってほしい気持ちになったんですが、ならなかったので復習しますcomparing solutions 1 and 0 Comparing declarations func f(_ v: any P) { return } and func f(_ v: some P) { return } (isDynamicOverloadComparison: 0) comparison result: better Comparing declarations func f(_ v: some P) { return } and func f(_ v: any P) { return } (isDynamicOverloadComparison: 0) comparison result: not better comparing solutions 1 and 0 better とは... この部分を判定してそうなコードはありました // A non-generic declaration is more specialized than a generic declaration. if (auto func1 = dyn_cast<AbstractFunctionDecl>(decl1)) { auto func2 = cast<AbstractFunctionDecl>(decl2); if (func1->isGeneric() != func2->isGeneric()) return completeResult(func2->isGeneric()); }
https://github.com/apple/swift/blame/4517333b8ef249d2d8774a5e62b00ed1042bd1f5/lib/Sema/CSRanking.cpp#L482 (edited)transformRec があったところにより柔軟な transformWithPosition が追加された時に、 transformRec の実装を transformWithPosition に流すようにしていたところをリファクタリングしてTypeTransform というベースクラスを作って、 transformRec と transformWithPosition をどちらもそれの継承による実装にしてるType::subst の実装が transformRec で実装されていたところを、これも TypeTransform の継承にしてるわね
1
1
1
1
4~Copyable は同時にSendable も満たすんですか?class Counter { var value: Atomic<Int> } (edited) /// The allocator for the task stack. /// Currently 2 words + 8 bytes. TaskAllocator Allocator; そうっぽい
1CommandLine.arguments で使う argv を parse している箇所を見つけました.そういえば compnerd さんが try! Swift で言ってたなぁと思いましたがまずは UTF-16 を UTF-8 に変換するところからなんですね.(議論が逸れてすみません) https://github.com/swiftlang/swift/blob/72615fe5fec917f6f3154f203d6a0c500d07da14/stdlib/public/CommandLineSupport/CommandLine.cpp#L401-L421
3
2
3
1
1
4Task { var a = 42 var p = UnsafeRawPointer(&a) print(a, p) await Task.yield() p = UnsafeRawPointer(&a) print(a, p) await Task.yield() p = UnsafeRawPointer(&a) print(a, p) }try は await 後に処理されるから try? | await
2Task { var a = 42 var p = UnsafeRawPointer(&a) print(a, p) await Task.yield() p = UnsafeRawPointer(&a) print(a, p) await Task.yield() p = UnsafeRawPointer(&a) print(a, p) } 42 0x00005bfc299aae28 42 0x00005bfc299aae28 42 0x00005bfc299aae28<stdin>:4:13: warning: initialization of 'UnsafeRawPointer' results in a dangling pointer 2 | Task { 3 | var a = 42
1as as? unsafeBitCast (edited)static_cast dynamic_cast reinterpret_castconst_castのSwift版あるかなvar value: Double = .zero みたいな左辺と右辺の比較が要る定義の仕方をしなくなりましたねvar value: Double = .zero みたいな左辺と右辺の比較が要る定義の仕方をしなくなりましたね struct Hoge {} func fuga(_ val: Hoge) {} fuga(.init()) みたいなのもですかね?
3swift play が実装された swiftpm フォークがあるよ https://github.com/swiftlang/swift-package-manager/compare/main...chrismiles:swift-package-manager:eng/chrismiles/swift-play-prototype (edited)@section はフォーラムで検討中の、バイナリへのデータ埋め込み制御用の機能だけど、これに使うんだねえswift play が実装された swiftpm フォークがあるよ https://github.com/swiftlang/swift-package-manager/compare/main...chrismiles:swift-package-manager:eng/chrismiles/swift-play-prototype (edited)@section で無理やりバイナリレベルでエクスポートしておくって仕組みなんだな$ swift play だと、説明を読む限りシェルのフォアグラウンドジョブとして居座り続けて、ソースコードの方を編集するとホットリロードされるっぽいんだよね#Playground 部分だけをコンパイルしてdylibにしてdlopenするのが理想なはずだけど、その部分だけをコンパイルするのだとfile privateスコープがビルド通せない気がするんだよな#Playgroud の部分だけをホットリロードするためにめっちゃでかいdylibができて、一回リロードされるたびにプロセスメモリがバンバン膨らんでいく気がする。
3treastrain を管理者に追加いただけますでしょうか
1
1
1
3@_cdecl (C calling convention) じゃなくて @_silgen_name (Swift calling convention) で大丈夫なんですね (edited)
1