テーマ 第一部: モダンなプログラミング言語としての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_FLAGS
func ==
いらない?// 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 #endif
protocol
で 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 4
dynamic_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 Error
init(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)true
stderr: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-a
true
/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-a
true
/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-a
Dictionary<String, String>.Type Dictionary<String, String>.Type
protocol 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-RELEASE
Any
と 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 8
typedef
について大阪 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 Index
var _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 coerce
Int?
だとしたら、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 P
any P
と <T: P> T
struct 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) }
<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:
f { } {} {} {} (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@0
commit 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-filing
func 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) -> URLSessionDataTask
URLSession.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/await
async/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-concurrencysuspendAsync
相当のものがないと作れないと思います。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-graphviz
if 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
専用のエラーメッセージあるわDouble.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.30000000000000004
Float80
サポートと共に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.1
0.10000000000000001
を2進表現した時の値は 十進でいえば 0.10000000000000001
のほうが 0.1
より近いんじゃあないんか。 (edited)#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.def
stdlib/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 OVERRIDE
git 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))
main.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'
${product_name}_${module_name}.${class_name}
a.components(separatedBy: "_")
ですかね?productname_modulename
が入ってそうだからそれでもいけますねa.components(separatedBy: "_")
ですかね? このようにバッククォート3つ
このようにバッククォート1つ
@mt.hodaka こうやるといいですよ waiwai-swiftc
チャンネル .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.57202205181a
func 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?>
@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.dynamicType
n.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() ^
print(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"-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-regex
let 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>>)>
foo[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)string & {
この時点でもう草まみれString & {
ならまぁ、良くはないがわからんでもない&
での合成は含まれるプロパティをマージするってことだから。HList
先輩を持ってくれば…… length
とかが出てくる keyOf
はランタイムでの動作で、型レベルにも keyOf
という型レベル計算が定義されていて、その2つの違いってことかな?length
はランタイムでメンバーのプロパティーが取れる的なことかと思ったけどそうでもないのか (edited)@ 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
に整理するのが設計の勘所かしら。all @*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 + 2 * 3]
(edited)1 + (2 * 3)
1+2+3 = 6
, 1*2*3 = 6
なので+と*は同じoperator precedence
文を読み取らないといけないから、パーサステージではできない。/aaa[0-1*/
←こういうの) コンパイルエラー出てくれるんでしたっけ。RegexのためのLexerあったら面倒見てくれそうな感じがするけどimport TypeScriptAST
import 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 * 8
protocol 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) } }
Foo<>
には、 直接の Repository と、 UserEditService の型パラメータの Repository と、 ZooEditService の型パラメータの Repository が3回出現しているので、 型パメータとして具体的な依存の実体である DatabaseRepository
を 3回書かないといけない。 しかもこれは Repository を利用するコンポーネントが増えるたびに増えていきます。 一般的な動的なDIコンテナだったら、 まず Repository を登録して、その他のそれを利用するサービスは、 自身の依存先を DIコンテナ自体から取り出す事によって構築するので、 「具体的なRepositoryが何であるか」という宣言(コード上の表明) は1箇所で良いはずが、 このアプローチだと自明なはずの事を何度も繰り返して書かないといけない問題がありそうです。 (edited)DummyRepository
に変える」というセットアップがしたいとします。 しかし、できない気がします。 共通部分も含めて、テスト用の構成をすべて書きくださないといけないとすると、 「ある一箇所だけスタブに変更する」という意味づけのコードが書けない気がします。let 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
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())
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)