swift-4.0.2-RELEASE来てた。String は StringProtocol だけど Number は Numeric なんですね… https://developer.apple.com/documentation/swift/numericStringProtocol 以外の XxxProtocol って何があります?IteratorProtocol 普通にわすれてたw NSObjectProtocol なんてあるのかぁ(白目public protocol NSObjectProtocol { ってなってるのに、実際の動きは public protocol NSObjectProtocol: class { なんじゃあないのっていうのが各所で浮き出てくる (edited)Iterator っていう 名前衝突を避けたくてそうなった感があるけどね・・・@objcつけたらclass矯正されるのと同じ感じですかね@objc明示ルール出来たのにNSObjectProtocolはそうじゃないっていうのもねinherits、何かの型がprotocolに準拠している場合は conforms、多分これで問題ないかと…?Int は型だから protocol に Conforms To ですねStatus を abstract class で定義できたらなぁとすごい思うstruct StackArray<value Size: Int> { ... }var a = StackArray<2>() a.0 // ok a.1 // ok a.2 // compile error (edited)enum Status { case NotReady case Ready } class Something<value T: Status> { /*中身は同じでOK*/ } (edited)value T: Status になってるのか。 (edited)Status が protocol じゃダメなんだっけ? sealed にできない?- Now you can define a “dependent type”, for example ModuloInteger<P>, where P is the integer value that defines the type. - Like this, you’ll have: —> MI<2>: {0, 1}, where 1 + 1 = 0. —> MI<3>: {0, 1, 2}, where 1 + 1 = 2, and 2 • 2 = 1Status が protocol でもダメってことはないですが、Something<NotReady>.createInstance() で書かないといけないのがイケてないですねVector<2> とか Matrix<4, 4> とかやりたい。reserveCapacity とか考えなくて済むstruct MultiArray<T, let Dimensions: Int> { // specify the number of dimensions to the array subscript (indices: Int...) -> T { get { require(indices.count == Dimensions) // ... } } (edited)struct Real { ... } extension Real : ConstructibleFrom<Float> { init(_ value: Float) { ... } } extension Real : ConstructibleFrom<Double> { init(_ value: Double) { ... } } サンプルも Rust の From trait と似てるenumでstateパターン、無理やりRawValueに振る舞いを実装して見た https://gist.github.com/norio-nomura/65db97c4786851bc368a8d68834fb31b (edited)RawRepresentable で実装where T: Ready で書くと問題ないけど、where T == Ready で書くと Something.createInstance() の直後でも変換の補完で .shout() が出るのなんで?(もちろんコンパイルエラーにはなるけど…)$ swift generate.swift で実行しているだけなんや。%{ let intTypes = [8,16,32,64] }% % for intType in intTypes { % for sign in ["", "U"] { /// Extension that adds a few additional functionalities to ${sign}Int${intType} extension ${sign}Int${intType} { /// Returns a ${sign}Int${intType} with all ones % if sign == "" { public static var allOnes: Int${intType} { return Int${intType}(bitPattern: UInt${intType}.max) } % } else { public static var allOnes: UInt${intType} { return UInt${intType}.max } % } } % } % }-alpha とか -beta つけるのオススメ。end とか Python じゃないし。-swift-version 3を渡してるかどうかは #if swift(>=3.2.2) で判定。 (edited)[omochi@omochi-iMac gysb (master *+=)]$ cat Examples/include.swift.gysb %! include_code("libs/*.swift") % aaa=${aaa()} bbb=${bbb()} [omochi@omochi-iMac gysb (master *+=)]$ swift run gysb Examples/include.swift.gysb aaa=999 bbb=777%! と include_code を追加したのでなんとかなるmaster *+= ってなんや%! swift_package("Package.swift") とか定義しておくと SPM の executable として実行するような機能を作ったら対応できそう。%{...}の中にimportは書けないのか[omochi@omochi-iMac gysb (master=)]$ swift run gysb --compile Examples/include.swift.gysb func write(_ s: String) { print(s, terminator: "") } func aaa() -> Int { return 999 } func bbb() -> Int { return 777 } write("aaa=") write(String(describing: aaa())) write("\n") write("bbb=") write(String(describing: bbb())) write("\n").gysbインプットから.swiftのStringを作れるAPIがあると、swift testの度に.swiftを生成する事ができる様になります。 (edited)#comment(lib, "GL.h") ってかいてリンク指定できるみたいな。 (edited)*.cをパッケージ内に持ってて、SwiftPMにClangモジュールとしてビルドしてもらってます。Run Script Phaseを使えるからCLIでいいけど、SwiftPMはビルドプロセスに入れられないのがネックだね。vapor build の手前に処理を差し込む方法ないのって問い合わせたらねえって言われた (edited)vapor cloud deploy するとリモートでチェックアウトして vapor build が動くんだけどその手前でコードジェネレータ動かしてもらわないと成果物コミットしてないから当然コンパイル通らないPackage.swiftの内容を切り替え、GYSB=1 swift testでコード生成し、swift testで生成したコードを利用する方法を思いついた。swift test --filter Generateとテストするモジュールを制限しても全てをビルドしようとするから、未生成なコードに依存する部分がビルド出来なくてダメだった。// swift-tools-version:4.0 import PackageDescription import Foundation let package: Package if ProcessInfo.processInfo.environment["GYSB"] != nil { package = Package( name: "Generate", dependencies: [ .package(url: "https://github.com/omochi/gysb.git", .branch("master")), ], targets: [ .testTarget(name: "Generate", dependencies: ["GysbKit"], path: "Tests/GenerateTests") ] ) } else { package = Package( name: "Example", products: [ .library(name: "Example", targets: ["Example"]), .library(name: "Generated", targets: ["Generated"]), ], targets: [ .target(name: "Example", dependencies: ["Generated"]), .target(name: "Generated", dependencies: []), .testTarget(name: "ExampleTests", dependencies: ["Example"]), ] ) }$ tree . ├── Package.resolved ├── Package.swift ├── README.md ├── Sources │ ├── Example │ │ └── BuildPhase.swift │ └── Generated │ └── vector.swift └── Tests ├── ExampleTests │ └── ExampleTests.swift ├── GenerateTests │ └── GenerateVectorTests.swift └── LinuxMain.swift こんな感じ (edited)Package.swiftでYamsをビルドして、それを.gysbの中でインポートしようとしてるのだけど、うまくいかないな。Test Case '-[GysbWithYamsTests.GysbWithYamsTests testExample]' started. process execution failure path=[/usr/bin/swift] arg[0]=[/var/folders/kt/2mwy9b_56_7993x190pl_1fh0000gn/T/vector_49IokLMk.swift] arg[1]=[-L] arg[2]=[/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug] statusCode=[1] stderr= /var/folders/kt/2mwy9b_56_7993x190pl_1fh0000gn/T/vector_49IokLMk.swift:4:9: error: no such module 'Yams' import Yams ^ Test Case '-[GysbWithYamsTests.GysbWithYamsTests testExample]' passed (0.438 seconds).$ /usr/bin/swift /var/folders/kt/2mwy9b_56_7993x190pl_1fh0000gn/T/vector_49IokLMk.swiftreturn try execCapture(path: swiftPath, arguments: [path, "-L", "/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug"]) (edited) -F <value> Add directory to framework search path-l も必要だったかはよくわからない-I…,-L…,-F…つけても、YamsのPackage.swiftでライブラリtypeを.staticや.dynamicにして-lYamsつけてもダメだ。 path=[/usr/bin/swift] arg[0]=[/var/folders/kt/2mwy9b_56_7993x190pl_1fh0000gn/T/vector_NwwoI7hu.swift] arg[1]=[-I] arg[2]=[/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug] arg[3]=[-F] arg[4]=[/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug] arg[5]=[-L] arg[6]=[/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug] arg[7]=[-lYams] statusCode=[1] stderr= /var/folders/kt/2mwy9b_56_7993x190pl_1fh0000gn/T/vector_NwwoI7hu.swift:4:9: error: no such module 'Yams' import Yams (edited).dynamicにして、以下のオプションをswiftに渡したらいけた。 return try execCapture(path: swiftPath, arguments: [ "-I", "/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug", "-L", "/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug", "-lYams", path, ])% import Foundation % import Yams % guard let yaml = try Yams.compose(yaml: String(contentsOf: URL(fileURLWithPath: "TestResources/vector/vector.yml"))) else { fatalError() } % let vars = yaml.array().flatMap { $0.string } % for n in 2...4 { struct Vector${n} { % for i in 0..<n { var ${vars[i]}: Float % } } % }swift run gysb が通る状態?// swift-tools-version:4.0 import PackageDescription let package = Package( name: "GysbWithYams", dependencies: [ .package(url: "https://github.com/omochi/gysb.git", .branch("master")), .package(url: "https://github.com/jpsim/Yams.git", .branch("master")), ], targets: [ .testTarget( name: "GysbWithYamsTests", dependencies: ["GysbKit", "Yams"]), ] )
class GysbWithYamsTests: XCTestCase { func testExample() { do { let driver = Driver.init(path: "TestResources/vector/vector.swift.gyb") let actual = try driver.render(to: .render) print(actual) } catch { print(error) } } static var allTests = [ ("testExample", testExample), ] } (edited)libYams.aかlibYams.dylibが無いとダメですね。type: .staticでも本当はいけると思うのですが、swiftcがクラッシュしてしまいダメでしたが。.o達を直接リンクします。 (edited)swift test -vとかしてみるとコンパイラの起動オプションを見られます。type: .dynamicにするとswift build --static-swift-stdlibとかしてもそれらのライブラリはダイナミックリンクされるみたいだから、今後は使い勝手が悪くなると避けられるんじゃないかな? (edited).dynamicなライブラリを同じパッケージ内のexecutableターゲットから使う場合は問題ないのですが、依存しているパッケージから使った場合、それらはフルパスでリンクされてしまい、ポータブルなexecutableではなくなってしまいます。 $ otool -L ./.build/x86_64-apple-macosx10.10/debug/gysbClient ./.build/x86_64-apple-macosx10.10/debug/gysbClient: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1445.12.0) /Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug/libGysbKit.dylib (compatibility version 0.0.0, current version 0.0.0) /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.0.0) (edited)prefix operator > prefix func >(value: String) { print(value) } let intTypes = [8, 16, 32, 64] for intType in intTypes { for sign in ["", "U"] { >""" /// Extension that adds a few additional functionalities to \(sign)Int\(intType) extension \(sign)Int\(intType) { /// Returns a \(sign)Int\(intType) with all ones """ if sign == "" { >""" public static var allOnes:Int\(intType) { return Int\(intType)(bitPattern: UInt\(intType).max) } """ } else { >""" public static var allOnes:UInt\(intType) { return UInt\(intType).max } """ } >""" } """ } } (edited)%{ intTypes = [8,16,32,64] }% % for intType in intTypes: % for sign in ['','U']: /// Extension that adds a few additional functionalities to ${sign}Int${intType} extension ${sign}Int${intType} { /// Returns a ${sign}Int${intType} with all ones %if sign == '': public static var allOnes:Int${intType} { return Int${intType}(bitPattern: UInt${intType}.max) } %else: public static var allOnes:UInt${intType} { return UInt${intType}.max } %end } %end %endManifestoGeneratorとか出来てる!w https://github.com/omochi/gysb/blob/master/Sources/GysbSwiftConfig/ManifestoGenerator.swift%! swift_config("gysb_swift_config.json") %{ import Foundation import Yams let yamlPath = URL.init(fileURLWithPath: "data.yml") let yamlStr = try! String(contentsOf: yamlPath, encoding: .utf8) let yaml = try Yams.compose(yaml: yamlStr)! let fields: [String] = yaml.array().map { $0.string! } }% struct Data { % for field in fields { var ${field}: String % } }{ "packageDependencies": [ { "url": "https://github.com/jpsim/Yams.git", "requirement": { "identifier": "0.5.0", "type": "exact" } }, ], "targetDependencies": [ { "name": "Yams" } ] }%! swift_config() の指定は1ファイルだけがする。%! swift_config("gysb_swift_config.json")gysb.json はどこにあるんだ?ってなっちゃうんですよね%! import("https://github.com/jpsim/Yams.git") とかするとswift_config()に渡すjson相当のものが自動で生成される様にするとか。%! import("https://github.com/jpsim/Yams.git") とかするとswift_config()に渡すjson相当のものが自動で生成される様にするとか。 これの問題点は、パッケージ名からターゲット名がわからないことimport 使えるんだっけ?libSwiftPMが気軽に使えれば「リポジトリからPackage.swiftを解釈して〜」とか簡単に出来そうなのに… https://github.com/apple/swift-package-manager/blob/master/Package.swift#L19%! swift_config("gysb_swift_config.json")brew install gysbできる様になると良いね。%! swift_config 以外に %! include_code っていうマクロ命令もあってswift_config 書く場合と同じでgysb Sources/Foo/*.gysb Sources/Bar/*.gysbgysb src/ で再帰的にgysb さがすの??gysb -r src/ とか明示的にした方が良さそうな気も。gysb.josn も全部適用で良さそう。 (edited)gysb Sources/Foo/*.gysb Sources/Bar/*.gysb みたいなことがしたいんじゃないの?swift_config を導入せずに gysb.json を置く方式にするのであれば、一つのディレクトリの中で設定を切り替えることはできないという意味です。Sources/Foo/gysb.json Sources/Bar/gysb.jsonSouces/gysb.json と Sources/Foo/gysb.json をマージ、 Souces/gysb.json と Sources/Bar/gysb.json して 2 回実行 Souces/gysb.json Sources/Foo/gysb.json Sources/Bar/gysb.jsonFoo/gysb.json 等に記述することを想定)Foo, Bar 以下のすべての gysb ファイルに対して 1 回で実行 Souces/gysb.json%! swift_conifig はやめてディレクトリ遡り探索の gysb.json にしようと思います%! という複雑性を持ち込まなくてよさそう。% func foo() { FooFooFoo % } % for _ in 0..<3 { % foo() % }FooFooFoo FooFooFoo FooFooFoofunc taxRate() -> Float { return 1.08 }%{ func taxRate() -> Float { return 1.08 } }metalib.swift.gysb とかになる。Sources/foo/a.swift.gysb // こいつが それを読みに行く Sources/foo/metalib/metalib.swift.gysb$ gysb --source-dir Sources を実行すると・・・Sources/foo/metalib/metalib.swift.gysb が 処理対象になって、 自分を自分の上部にincludeしようとして、無限ループして壊れる。func taxRate() みたいな、ちょっとしたやつ。%! 的な構文は避けられなさそう。%! から逃げられないですね%! include("path/to/file") の行をそのファイルの中身で展開するだけ。{% include footer.html %}{% include {{ page.my_variable }} %}% for i in 0..<10 { %! include("file\(i).gysbi") % }%! のマクロ言語はテンプレート処理系の前段にあるとしていますinclude を関数として実装できないかな?write するgysbi ファイルに対して gysb を実行して得られた文字列を挿入すれば。%! も排除できる。brewのバイナリ配布、sourceryがSwiftPMでビルドしたものを使ってる。 https://github.com/Homebrew/homebrew-core/blob/master/Formula/sourcery.rbbottles do ... end にバイナリの置き場所書けば対応で、省略すればインストール先でビルド必要な認識でした。 (edited)[swift-evolution] update on forum Ted Kremenek via swift-evolution The decision to move to a forum was announced a while ago, and it hasn’t appeared yet. I think we will be making the move soon and I wanted to provide some reasons why it was delayed and what comes next. ... My hope is that process will start in December.yaml ならいけるかもしれませんが、 gysb の実行に YAML パーサが必要になって依存が生まれてしまいそう・・・ 一応書いておくと、YamsはCodableをサポートしたYAMLパーサです。Yams自身には外部ライブラリ依存はなくて、利用実績としてはSwiftLintが.swiftlint.ymlのパースに使っています。$(brew --repository homebrew/core) git remote add omochi https://github.com/omochi/homebrew-core.git したら、次のコマンドでformula作成: brew create https://github.com/omochi/gysb/archive/0.8.6.tar.gz して、出来たgysb.rbのdepends_on, def install, test doを https://github.com/Homebrew/homebrew-core/blob/master/Formula/sourcery.rb 辺りを参考に設定して、 brew install --verbose --debug gysb でインストールテストして、 cd $(brew --repo homebrew/core) git checkout -b gysb git add Formula/gysb.rb git commit git push https://github.com/omochi/homebrew-core/ gysb してPR、って感じかな?Makefileとか不要。class Gysb < Formula desc "Generate your swifty boilerplate" homepage "" url "https://github.com/omochi/gysb/archive/0.8.6.tar.gz" sha256 "139fd7225442c74e943b32716158a3ea5bd438241372a3cf913fd5313793248e" depends_on :xcode => ["9.0", :build] def install system "swift", "build", "--disable-sandbox", "-c", "release", "-Xswiftc", "-static-stdlib" bin.install ".build/x86_64-apple-macosx10.10/release/gysb" end test do # `test do` will create, run in and delete a temporary directory. # # This test will fail and we won't accept that! For Homebrew/homebrew-core # this will need to be a test that verifies the functionality of the # software. Run the test with `brew test gysb`. Options passed # to `brew install` such as `--HEAD` also need to be provided to `brew test`. # # The installed folder is not in the path, so use the entire path to any # executables being tested: `system "#{bin}/program", "do", "something"`. system "true" end endtest doにsystem "true"とか書いたけど、そこは真面目に書き換えないといけない。sourcery --versionで返すかどうか、かな。+struct ParameterizedStruct<T> { + mutating func takesFunctionWithGenericReturnType(_ f: (Int) -> T) {} +} これがArrayに相当してるのかgit tag --contains cf9a09e18dba7a7fe0506381589fbf0f4bb99a98 で何も出ない。swift-DEVELOPMENT-SNAPSHOT-2017-11-21-a出てる。func processPo<X: ConstPo>(po: X, process: (X.Element) -> Void) { これでokconst の場合と違って、型ごと CostoPo を満たさないといけないの微妙そう。struct じゃダメ? Swift の class は二級市民だと思ってる。View に対応した ViewModel を struct で作って渡すとか?View 自体を操作する関数だとダメだけど。const にしたいくらいだから View から情報をとりたいだけに見える)enum Hoge { case fuga(Int) case piyo(Int) var count: Int { switch self { case .fuga(let count), .piyo(let count): // <- ここ return count } } }let count だからいける?protocol ProtocolA {} enum Hoge { case fuga(ProtocolA) case piyo(ProtocolA) var count: ProtocolA { switch self { case .fuga(let count), .piyo(let count): return count } } }Playground execution failed: error: MyPlayground.playground:5:24: error: matching a protocol value in multiple patterns is not yet supported; use separate cases instead case .fuga(let count), .piyo(let count): ^protocol ProtocolA {} enum Hoge<T: ProtocolA> { case fuga(T) case piyo(T) var count: T { switch self { case .fuga(let count), .piyo(let count): return count } } }let a: Int? = 42 if case let a? = a { print(a) } int *a = ...; *a = 42; って書くのと似てるよね。 (edited)*a が int 型というのと、 a? が Int 型というのが。a? は Int 型ではないですよねa? は Optional<Int> だからこそ a の部分だけが Inta? は Int? で a が Int か。*a が int で a は int * 。protocol ProtocolA {} enum Hoge<T: ProtocolA> { case fuga(T) case piyo(T) func value<T>() -> T { switch self { case .fuga(let value), .piyo(let value): return value } } }
error: MyPlayground.playground:6:20: error: cannot convert return expression of type 'T' to return type 'T' return value ^~~~~ as! Ttypealias Tuple = (Int, String) enum Hoge { case fuga(Int) case piyo(Tuple) var value: Int { switch self { case .fuga(let value), .piyo((let value, _)): return value } } } case let [first, second, third]: みたいな。error: MyPlayground.playground:6:20: error: cannot convert return expression of type 'T' to return type 'T' return value ^~~~~ as! T これは真っ当なエラーでは…Token と tok と Tok が出てきて、Tok の定義が全然見つからないと思ったら Token 型のフィールド名が Tok だった・・・tok は enumsnake_case_ ですね、他のC++プロダクトをそんなに読んでないのでわからないですがCMake -G XcodeTok でジャンプできたぞw--release-debuginfo --xcode でビルドしたらclang: error: no such file or directory: '/Users/omochi/work/swift-source/build/Xcode-RelWithDebInfoAssert/cmark-macosx-x86_64/src/Debug/libcmark.a' と出ていて (edited)/Users/omochi/work/swift-source/build/Xcode-RelWithDebInfoAssert/cmark-macosx-x86_64/src/RelWithDebInfo/libcmark.a--release-debuginfo なのに cmark は --debug で参照しちゃっててうまくいってないみたいなんですけど--xcode は作業用、 ninja でビルド するのが良いのか? release-debuginfo があまりメンテナンスされていないので、 release にするのが良いのか? とか、どうなんでしょう--xcode のせいなのか、そうでないのか調べるために ninja でもやってみます。 /Users/omochi/work/swift-source/build/Xcode-ReleaseAssert/swift-macosx-x86_64/Release/bin/swiftc -apinotes -yaml-to-binary -o /Users/omochi/work/swift-source/build/Xcode-ReleaseAssert/swift-macosx-x86_64/Release/lib/swift/macosx/x86_64/ScriptingBridge.apinotesc -target x86_64-apple-macosx10.9 /Users/omochi/work/swift-source/swift/apinotes/ScriptingBridge.apinotes /Users/omochi/work/swift-source/build/Xcode-ReleaseAssert/swift-macosx-x86_64/Release/bin/swiftc -apinotes -yaml-to-binary -o /Users/omochi/work/swift-source/build/Xcode-ReleaseAssert/swift-macosx-x86_64/Release/lib/swift/macosx/x86_64/ScriptingBridge.apinotesc -target x86_64-apple-macosx10.9 /Users/omochi/work/swift-source/swift/apinotes/ScriptingBridge.apinotes 出力先 /Users/omochi/work/swift-source/build/Xcode-ReleaseAssert/swift-macosx-x86_64/Release/lib/swift/macosx/x86_64 が存在してなかったが、 /Users/omochi/work/swift-source/build/Xcode-ReleaseAssert/swift-macosx-x86_64/Release/lib/swift は存在していたので、 mkdir してやったら、いけました。class ViewBindingHelper<Model> { ... } protocol ViewBindingHelperUser { associatedtype Model var helper: ViewBindingHelper<Model> { get } } extension ViewBindingHelperUser { 追加される機能 }class ProductListTableView : NSTableView, ViewBindingHelperUser { let helper: ViewBindingHelper<ProductList> = .init() } (edited)User の方のプロトコルコンフォーマンスは解除して、 .helper.method でヘルパ名をネームスペース代わりにするしか無さそう。protocol MyViewProtocol { var button: Button { get } } protocol HasMyViewProtocol: MyViewProtocol { associatedtype MyView: MyViewProtocol var myView: MyView { get } } extension HasMyViewProtocol { var button: Button { return myView.button } }extension MyViewProtocol に置けば全部使えるようになる-swift-version 3を使うとSwift 3.3になるぽい。 $ TOOLCHAINS=org.swift.4120171207a swift -swift-version 3 Welcome to Apple Swift version 4.1-dev (LLVM 67b9a8e8c2, Clang e617c83242, Swift 65b4172032). Type :help for assistance. 1> #if swift(>=4.1) 2. let versions = "swift-4.1" 3. #elseif swift(>=4.0.3) 4. let versions = "swift-4.0.3" 5. #elseif swift(>=4.0.2) 6. let versions = "swift-4.0.2" 7. #elseif swift(>=4.0) 8. let versions = "swift-4.0" 9. #elseif swift(>=3.3) 10. let versions = "swift-3.3" 11. #elseif swift(>=3.2.3) 12. let versions = "swift-3.2.3" 13. #elseif swift(>=3.2.2) 14. let versions = "swift-3.2.2" 15. #else // if swift(>=3.2) 16. let versions = "swift-3.2" 17. #endif 18. versions: String = "swift-3.3" 18> (edited)subject.value() がthrowsなのってなんでなんだろAVAudioFile もなぜか AVAudioFramePosition は Int64 なのに AVAudioFrameCount は逆に UInt32 しかないという不可解な現象 https://qiita.com/lovee/items/8bdf7b58d96d683d31b9AUAudioFrameCount で自分が上げたのは AVAudioFrameCount なんですよな…This alias is type `uint32_t` for impedance-matching with the pervasive use of `UInt32` in the Audio Toolbox framework and the C Audio Unit framework APIs, as well as the `AVAudioFrameCount` data type. (edited)var length: AVAudioFramePosition The number of sample frames in the file. typealias AVAudioFrameCount A number of audio sample frames. この説明がすでに色々理不尽な気が…(CのAPIに合わせてるのなら逆にじゃあなぜCではcountだけが32bitなのか…ComponentResult AudioUnitRender( AudioUnit ci, AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData ) inNumberFrames The number of frames to be rendered. (edited)SInt32 startBufferOffset これだけ読むとやはりCでは両方32bitにしてるけどAVFoundationがなぜかpositionだけ64bitにしてるんですよね… (edited)UInt32 bufferOffset; bufferOffset Where in the current buffer the event should occur (edited)GL_PROJECTION // Int32 glMatrixMode(GLenum(GL_PROJECTION)) // Obj-C (C) ではそのまま渡せた (edited)static var GL_PROJECTION: GLenum ってオーバレイ用意してほしいですね。#define だったマクロがそのまま Int32 としてポーティングされてしまっている#defineの数値リテラル?はInt32になるよね (edited)#include <stdio.h> #define BIG_NUMBER (0xffffffffffffffff) void printHex(unsigned long long number) { printf("%llx\n", number); } int main(void) { printHex(BIG_NUMBER); return 0; }#define NAME "aaa" みたいなのもありえるので#define は型を判定してるのかな?AVFoundation.framework/Frameworks/AVFAudio.framework/Headers/AVAudioTypes.h
/*! @typedef AVAudioFrameCount @abstract A number of audio sample frames. @discussion Rationale: making this a potentially larger-than-32-bit type like NSUInteger would open the door to a large set of runtime failures due to underlying implementations' use of UInt32. TODO: Remove rationales. */ typedef uint32_t AVAudioFrameCount;TODO: Remove rationales. は具体的に何を指しているのか… int が double に暗黙の型変換されてて、 double c = a / b; ( a と b が Android の API のコールで int が返される)の精度が落ちてしまっている事例が社内で発覚した。やっぱり数値間ですら暗黙の型変換を許さない Swift の方向性は正しかったんだ〜/ 書く時はトラウマが呼び起こされてミスしない体になったc の型を書かずに let にしていた結果、 Int のまま以降の行まで型推論が伝搬していって、/ 書く時は周囲に型をだいぶ明示的に書きたくなるlet t = 1 / 2 ... なんか処理 ... TimeInterval(t)/ は常に実数除算への昇格で、 整数のあまり切り捨て除算は別の演算子になってることもあるね。$ python Python 3.6.1 (default, Apr 19 2017, 14:30:24) [GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.41)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> 3 / 2 1.5 >>> 3 // 2 1// があった気がしてたけどpythonか。JSONEncoderのconvertToSnakeCase はmyURLPropertyをmy_url_propertyに変換するのだけれど、JSONDecoderのconvertFromSnakeCaseはmy_url_propertyをmyUrlPropertyへ変換するので、デコードに失敗する。 https://bugs.swift.org/browse/SR-6629convertFromSnakeCaseの実装がまずい。既存CodingKeysのstringValueのlowercasedとJSONのキーから_を削除した文字列を比較して、一致するCodingKeysメンバを決定しないといけない。 (edited)Stringに汎用のsnake_casedプロパティとかあった方が良さそう。CodingKeys の stringValue から、 encoder側の convertToSnakeCase と同じ変換をかけてから そのキーで JSON のバリューを読めば、ストレートな処理になりませんか? 今の実装のconvertFromSnakeCaseが色々な表記ゆれをサポートしてるせいで、その方法で上位互換にするのは無理かも。 (edited)YAMLDecoderで試しに実装してみた。 https://github.com/jpsim/Yams/pull/92JSONDecoderの実装は無駄に凝りすぎだと思う。typedef NS_ENUM(NSInteger, State) { StateHoge = 0, StateHuga = 1, }; Swift: let state = State(rawValue: 100)! switch state { case .hoge: print("hoge") // ★↑これが実行される case .huga: print("huga") }State(rawValue: 100) が nil にならないところが Swift 的に変で、そこのチェックが漏れてるのかもしれませんね。state.rawValue は 100 ですか? 0 ですか?switch で何が起こるかは仕様として決まってないんじゃないかと思います。#include <Foundation/Foundation.h> typedef NS_ENUM(NSInteger, State) { StateHoge = 0, StateHuga = 1, }; main.swift public func foo(state: State) -> Int { switch state { case .hoge: return 1 case .huga: return 2 } } let s = State(rawValue: 100)! print(foo(state: s)) 実行 $ swift -import-objc-header enums.h main.swift 1 $ swift -O -import-objc-header enums.h main.swift 2 (edited)-O 有無で結果が違うのはちょっと受け入れられない。Numeric って ExpressibleByIntegerLiteral を継承してるのに Int のイニシャライザに Numeric を受けるやつないのか…?// Integer literals are limited to 2048 bits. というコメントが。 https://github.com/apple/swift/blob/0cf1b52452f56b3bbdf2f2305cc10fef42bdff8b/stdlib/public/core/Policy.swift#L99 (edited)Numeric が ExpressibleByIntegerLiteral なのはよくわかんないですよね。行列とかで使えなくなっちゃいますし。Numeric よりも、群・環・体 https://qiita.com/taketo1024/items/733e0ecf12da359db729 みたいなプロトコルほしいですよね。Addable, Multipliable とかの方がプログラミング的には使い勝手がいいのかも?BinaryIntegerとFloatingPointで分けて実装してるのが一本化できるString って subscript { set } ができないからイミュータブルなのかと思ってたけど違った。 1> var s = "ABC" s: String = "ABC" 2> s.removeLast() $R0: Character = { _representation = smallUTF16 { smallUTF16 = 67 } } 3> print(s) ABsubscript { set } ができないのは、 Character が何バイトか定まらないから O(1) で実現できないからか。subscript { set } を実現できない。append とか removeLast とかって MutableCollection についてるのかと思ってたけど違った。で、 subscript { set } がないから String は MutableCollection じゃないだろう→ append や removeLast もないだろうと思って勘違いしてた。 https://developer.apple.com/documentation/swift/mutablecollection (edited)String でも平均 O(1) で実現できて問題ないのか。 (edited)faillthrough のユースケース?それとも^のコードですか?func tokenize(source: String) -> [Token] { let state = State(input: source) for character in state.input { switch state.mode { case .plain: switch character { case "'": state.mode = .symbol case "\"": state.mode = .string case "\n": state.mode = .newline state.storage = "" case "(", ")", ":": state.tokens.append(Token(type: .token, value: String(character))) case " ": break default: state.mode = .token state.storage = String(character) }protocol ValueProducer { associatedtype Value var value: Value { get } } ↑これ自作してさprotocol ValueProducer : ObservableConvertible { associatedtype Value var value: Value { get } }#if _runtime(_ObjC)でのStringのhashValueはそもそも文字列全体を使わないはずです。
import Foundation let first32Char = repeatElement("f", count: 32) let middle32Char = repeatElement("m", count: 32) let last32Char = repeatElement("l", count: 32) let a = (first32Char + ["ab"] + middle32Char + ["ab"] + last32Char).joined() let b = (first32Char + ["bc"] + middle32Char + ["bc"] + last32Char).joined() a == b // false // Foundation a.hash // -4528083392938427260 b.hash // -4528083392938427260 // Swift.Hashable a.hashValue // -8957072229412966235 b.hashValue // -8957072229412966235hashは同じ。hashをファイル変更検知に使ってバグってたことがあった時に調べた。 https://github.com/realm/SwiftLint/issues/1184#issuecomment-274744331enum HogeType: Int { case aaa = 1 case bbb case ccc } ↑ この書き方嫌いなんですけど、意外と賛同してくれる人少ないんだろうかと思ってるんですがどうですか enum HogeType: Int { case aaa = 1 case bbb = 2 case ccc = 3 } IntのrawValueつけるなら全case明示してほしい。Raw value for enum case is not unique というエラーが出たclass A { weak lazy var hoge: B? = nil } class B {} これなんか変なコンパイルエラーなったPlayground execution failed: error: cannot convert return expression of type 'B?' to return type 'B?' error: cannot assign value of type 'B?' to type 'B??' error: cannot assign value of type 'B?' to type 'B??'lazy なくすとエラーなくなるんだけど、 lazy ってその変数の型には影響しないよねweak + lazy ? が参照持てないし使えないのかなと思ったりretain count が増えないのが問題なのかなと思いました ってうまく説明できそうな気がしたが感覚でしかわかってないな。。。cannot assign value of type 'B?' to type 'B??' で、lazyが無いとそのエラーが消えるということは、lazyのあるなしでそのプロパティの型が実は変わっているようなきがするclass A { weak lazy var hoge: B? = B() } class B {} でもこれはこれですぐ解放されるので あまり通って欲しくもない気がするclass A { weak lazy var hoge: B = B() } class B {}
nil になるならまだいいんですけど これだとなおわからない気がするnil になっちゃうんですね class A { lazy var hoge: B! = B() } class B {} let a = A() a.hoge a.hoge = nil a.hoge あー、じゃあ、僕の会話していた時の頭の中が古かった 前まではもう一度初期化されていたはずだから weak + lazy ??? ってなってましたlet a = A() a.hoge // B a.hoge = nil // nil a.hoge // nil Swift3 let a = A() a.hoge // B a.hoge = nil // nil a.hoge // B こういうこと3.1 かどうかは置いておいてこういう時代があったんですよね ResolvedB?? と解釈されてるかどうかが変わっているきがするんだけどどうclass A { weak lazy var hoge: B? = { return B??.none }() } class B {}Playground execution failed: error: cannot convert return expression of type 'B?' to return type 'B?' error: MyPlayground.playground:4:30: error: cannot convert value of type 'B??' to specified type 'B?' weak lazy var hoge: B? = { ^ error: cannot assign value of type 'B?' to type 'B??' error: cannot assign value of type 'B?' to type 'B??'let articlesVC = ArticlesViewController.init { return ArticlesViewModel.init(dataProvider: ArticlesAPIDataProvider.init()) } 本番のコードなんで文脈なくてすまんやけどuninitialized() にすればいけんちゃうみたいなuninitialized() は中身fatalErrorの func uninitialized<T>() -> Tclass VC {} class VM { private weak var _vc: VC? = nil var vc: VC { get { return _vc ?? undefined() } set { _vc = vc } } }class LazyWeak<T> { private weak var _value: T? = nil private func undefined() -> T { fatalError() } var value: T { get { return _value ?? undefined() } set { _value = value } } } class VM { var vc = LazyWeak<VC>() } こういうイメッジclass A { unowned lazy var hoge: B = B() } class B {}Playground execution failed: error: cannot convert return expression of type 'B' to return type 'B' error: MyPlayground.playground:4:32: error: cannot convert value of type 'B' to specified type 'B' unowned lazy var hoge: B = B() ^~~ error: cannot assign value of type 'B' to type 'B?' error: cannot assign value of type 'B' to type 'B?'hoge: B! だとなんか違う怒られするclass A { var block: (() -> ()) = {} func hoge(block: @escaping (() -> ())) { self.block = block block() } } class VC { func viewDidLoad() { let a = A.init() a.hoge { [unowned self] in print(self) } } } VC.init().viewDidLoad()__lldb_expr_98.VC.rx が 生えてるやつでできることを、それ単体だけ Rx 全部を導入しないで採用できないか、ってのがコアアイデアですかね?class DelegateHolder { weak var delegate: SomethingDelegate? } let holder = DelegateHolder() // これは弱参照で持ってほしい。 holder.delegate = SomethingDelegateImpl() // これは強参照で持ってほしい。なぜなら、これを弱参照にすると map の戻り値の参照を誰も保持してないのですぐに回収されてしまうから。 holder.delegate = SomethingDelegateImpl() .map { a in a * 2 } // この差異を吸収するために、weak と strong の両方を持てるインターフェースを持つ必要があった。これを実現しているのが AnyDelegate。GenericError みたいな型を定義するError を定義する。言語仕様の方のやつと衝突しちゃうのでそっちを使う時は Swift.Error と完全名で記述するNSError を使うprotocol DescribedError: Error, CustomStringConvertible { }typealias DescribedError = Error & CustomStringConvertible とかでもいいのかな。enum Error: DescribedErrorって書きたいからextension String : Error {} func a() throws { throw "error message" } do { try a() } catch let e { print(e) // "error message\n" }XCTAssert(max(a, b) == c) | | | | | 7 4 7 | 12 false XCTAssert(a + b > c) | | | | | 4 | 7 | 12 11 false XCTAssert(john.isTeenager) | | | false Person(name: "John", age: 42) XCTAssert(mike.isTeenager && john.age < mike.age) | | | | | | | | | false | | 42 | | 13 | | | | Person(name: "Mike", age: 13) | | | false | | Person(name: "John", age: 42) | false Person(name: "Mike", age: 13)swift-power-assert xctest -Xxcodebuild test -workspace <workspacename> -scheme <schemeName> -sdk iphonesimulator -destination "name=iPhone X,OS=11.2"Chris_Lattner3 とかいう、めっちゃアカウント生成トラブった感じの名前になってるけどwRelease_Notes_for_Xcode_9.3_beta.pdf より ## Known Issues in Xcode 9.3 beta ### Swift Compiler - Conditional conformances are unsupported when performing a dynamic cast (with is or as). これってSwift 4.1リリースでも直らないんだよね? (edited)protocol P { } extension Int: P { } // Fully supported: Set unconditionally conforms to P extension Set: P { } // Not supported in dynamic casts: Array conforms to P // only when its element conforms to P extension Array: P where Element: P { } func castToP(_ value: Any) { if value is P { print("\(type(of: value)) conforms to P"); } else { print("\(type(of: value)) does not conform to P") } } castToP(Set([1, 2, 3])) // unconditional conformances // are supported: // prints "Set<Int> conforms to P castToP([1, 2, 3]) // unsupported conditional conformance: // incorrectly prints "Array<Int> does not // conform to P" castToP([3.141593, 2.71828]) // unsupported conditional conformance: // correctly prints "Array<Double> does not // conform to P" (edited)flatMapのdeprecationはSwift 4.1とSwift 3.3両方だから、4.0.xと3.2.x互換を維持する場合のcompactMap定義は #if (!swift(>=4.1) && swift(>=4.0)) || !swift(>=3.3) extension Array { public func compactMap(_ transform: (Element) throws -> String?) rethrows -> [String] { return try flatMap(transform) } } … みたいに書く必要があるのか。 (edited)#if (!swift(>=4.1) && swift(>=4.0)) || !swift(>=3.3)だった。public protocol Po { func doHoge() } extension Po { public static func getDefaultInstance() -> Po { return DefaultPo() } } internal class DefaultPo: Po { func doHoge() {} } // let po = Po.getDefaultInstance() <- Compile error let po = DefaultPo.getDefaultInstance() なのに今さら気づいた… Protocol は適合する対象であって型としては存在はしないんだなぁというのを実感したfunc hoge(po: Po) // dame func hoge<X: Po>(po: X) // OK なのも実感として納得がいった (edited)assertやpreconditionにクロージャ渡せたらループチェックとかかきやすくて良いんじゃないかと思うんですがどうですかね? もとの定義が@autoclosureなのでそれはずしたのをオーバーロードするだけで行けると思うんですが。assertやpreconditionは最適化によってconditionを評価しないだけで呼出し自体が消えるんじゃないみたいですね。 ずっと勘違いしてました。condition is not evaluated in /// -Ounchecked builds. In -Ounchecked builds, condition is not evaluated, but the optimizer may assume that it always evaluates to true. Failure to satisfy that assumption is a serious programming error.precondition(items.all { $0 >= 0 }) これでいいじゃんlet a = [0, 2, 4, 6] assert({ // all even for e in a { guard e % 2 == 0 else { return false } } return true }())() を消したいってこと?typealias CountableRange がなかったんですが、 4.1 でそれを突っ込むと結構大きめの破壊的変更になる気が。これは 5 で入る PR ですか?typealias でも破壊的か。オーバーロードとか死ぬし。 (edited)typealias O<X> = Optional<X> where X: Sequence O<String>.some("a") O<Int>.some(1) // Error 壊れなくなった可能性があるtypealias O<X> = Optional<X> where X: Sequence O<String>.some("a") //O<Int>.some(1) // Error extension O { func foo() { print("foo") } } Optional<Int>.some(1).foo() //????Swift compiler integration with external tools Potential mentors Rintaro Ishizaki## Swift compiler integration with external tools ## Integration of libSyntax with the rest of the compiler pipeline. ### Potential mentors Rintaro Ishizaki (edited)What are the eligibility requirements for participation? ・You must be at least 18 years of agedo使う場合は変数多くてメソッド分けたくない場合な気がしますねlet hogeObservable と let fugaObservable をこねこね作って、Observable.merge(hogeObservable, fugaObservable) みたいに書きたい時に、 hogeObservable と fugaObservable というローカル変数はなるべくスコープを短くしたいhogeFugaSubscription: do { ... }do 派です。ローカル関数やクロージャ式にすると実行順がコードの記述順と入れ替わる可能性があり、それを意識しないといけないのが難点だと思います。{ ... }() はわかってればいいけど可読性的に微妙かなと。do だと内部から break 等できるけど、ローカル関数やクロージャ式だとできないというのもあります。{ ... }() の方が読みやすい感覚があるんですよね。do{}はパッと見てtryか、と思ってしまうので。do { ... // 開始処理 defer { ... // 終了処理 } guard ... { ... break } ... }do を抜けるタイミングで終了処理を挟み込みたかったんですが、早期脱出もしたかったので、両方の終了処理を共通化しようとしたらこうなったけど、可読性は低いよなぁと。共通化を諦めて個別に書いた方がいい気もしてます。 while ... { do { ... // 開始処理 defer { ... // 終了処理 } guard ... { ... break } ... } ... }do より関数やメソッドに分割が望ましいと思います。
public func AAAAAAA(x: Int) { func step1() { /* ... */ } func step2() { /* ... */ } step1() step2() } public func BBBBBBB(x: Int) { ({ // step 1 /* ... */ })() ({ // step 2 /* ... */ })() } public func CCCCCCC(x: Int) { STEP1: do { /* ... */ } STEP2: do { /* ... */ } }
/* ... */ に十分長い処理を書いて試したところ、-O でも 内部 func と クロージャはインライン化されなかったです。ちょっと意外。LOOP: while ... { ACT1: do { ... // 開始処理 defer { ... // 終了処理 } guard ... { ... break ACT1 } ... } ... } こうかなdo を使うといいながらメソッドに切り出した方がいいというのは変だ・・・。func step1() {の定義は自然に読み飛ばすので、私の目には step1() step2() だけに見える。CCCCCCC が読みやすいですね。do を使いたいという気持ちでした。
let a = ... let b: B do { let t = ... // ちょっと複雑な式 b = foo(t, a) } let c = ...t を foo() の中に書けるけど、可読性のために変数に入れて名前を付けたくて、かといってそれを長々と生かしたくないみたいなケースです。t で済む一時変数にどこで何に使われてるかわかる説明的な名前を付ける必要が出てきませんかt という名前を付けることを意図したわけじゃないですが、僕はそのコンテクストでできるだけシンプルな名前を使うのが好きなので、後続処理と名前がかぶって困るということは結構ある気がします。do なくてもいいんですが、 10-20 行くらいになってくると一度スコープ切っておきたいですね。func これこれこういうイベントで発火するObservableだよ() -> Observable<E> func viewDidLoad() { これこれこういうイベントで発火するObservableだよ() .subscribe { 期待した結果やで } .disposed(by: disposeBag) }func setupこれこれこういうイベントで発火する奴() { viewModel.hoge.subscribe().disposed(by: bag) } こうなってるのがいっぱいある。func これこれこういうイベントで発火するObservableだよ() -> Observable<E> <= これ自体は何回呼んでも、いつ呼んでもいいわけですよね?func outer() { var state1 = ... var state2 = ... func inner1() { } func inner2() {} inner1() inner2() } ↑これ系のスタイルはclass HogeSetUpHelper { var state1 var state2 func inner1() func inner2() func setUp(...) } func outer() { HogeSetUpHelper().setUp(self) }HogeSetUpHelper().setUp(self)viewDidLoad と viewDidUnload の話だ。class X { lazy var setup: Void = { // only 1 time call here }() }_ = setup ?class X { lazy var setup: () -> Void = { print("a") return { } }() } let x = X() x.setup() ほらよ (edited)func nop() { } typealias Setup = () -> Void class X { lazy var setup: Setup = { // 1回だけ return nop }() } 少し見た目をマシにしてみたlet setup = once { } こういう高階関数作れそうじゃない?fooLoop { (`break`: () -> Never) in ... } みたいな break を作りたかったけどできなくて悲しくなった。lazy 内 で self 参照出来るっていうのは正式にOKになったんだっけか。func nop() {} func once(_ f: () -> Void) -> () -> Void { f() return nop } class X { lazy var setup = once { print("1time?") } } let x = X.init() x.setup() x.setup()public func once<T, R>(_ f: @escaping (T) -> R) -> (T) -> R { var done: Bool = false return { (t: T) -> R in guard !done else { fatalError("do not twice") } done = true return f(t) } } (edited)public func once<T, R>(_ f: @escaping (T) -> R) -> (T) -> R { var done: Bool = false return { (t: T) -> R in guard !done else { fatalError("do not twice") } done = true return f(t) } } public class Cat { public init(name: String) { self.name = name self.onBorn() } public var name: String public func onBorn() { _onBorn(self) } private let _onBorn: (Cat) -> Void = once { `self` in print("\(self.name)がうまれた") } } Cat(name: "tama")onBorn を let にしたかったけど self がキャプチャできなかったので func onBorn と let _onBorn に分かれてしまう。public class Cat { public init(name: String) { self.name = name self.onBorn() } public var name: String public lazy var onBorn: () -> Void = once { [unowned self] in print("\(self.name)がうまれた") } }once動かないのでは。public func once<T, R>(_ f: @escaping (T) -> R) -> (T) -> R { var done: Bool = false return { (t: T) -> R in guard !done else { fatalError("do not twice") } done = true return f(t) } } class Cat { let born = once { () in print("mew") } } let c = Cat() c.born(()) c.born(())public class Cat { public init(name: String) { self.name = name self.onBorn() } public var name: String public lazy var onBorn: () -> Void = once { [unowned self] in print("\(self.name)がうまれた") } }[weak self] _ in guard let `self` = self else { return } これで (edited)deinitちゃんと呼ばれるのね。 func once(_ f: () -> Void) -> () -> Void { f() return {} } public class Cat { public init(name: String) { self.name = name self.onBorn self.onBorn } public var name: String public lazy var onBorn = once { print("\(self.name)がうまれた") } deinit { print("deinit") } } do { Cat(name: "test") }onceがVoidではなく() -> Voidを返すのも地味に良い。Voidだとlazyの受け側に型指定がないとwarningが出るので。lazyでself参照出来るようになったのはSwift 4.0から?public struct S { init() {} public lazy var p = self.f() func f() -> String { return "f()" } } var s = S() s.p が error: use of unresolved identifier 'self' public lazy var p = self.f() ^~~~ になります。 (edited)swift-4.0-DEVELOPMENT-SNAPSHOT-2017-06-06-a以降ですね。if caseパターンって、キャスト?もされるのね。知らなかった。 import Foundation enum MyErrorEnum: Error { case message(String) } struct MyErrorStruct: Error {} class MyErrorClass: Error {} extension String: Error {} func check(error: Error) { if case MyErrorEnum.message = error { print("expected error: \(error)") } else { print("unexpected error: \(error)") } } check(error: MyErrorEnum.message("error")) check(error: NSError(domain: "custom error", code: -1, userInfo: nil)) check(error: MyErrorStruct()) check(error: MyErrorClass()) check(error: "StringError")
expected error: message("error") unexpected error: Error Domain=custom error Code=-1 "(null)" unexpected error: MyErrorStruct() unexpected error: __lldb_expr_90.MyErrorClass unexpected error: StringError (edited)XCTAssertThrowsError(try YAMLDecoder().decode(Sample.self, from: invalidYaml)) { error in if case DecodingError.typeMismatch(_, _) = error {} else { XCTFail("unexpected error: \(error)") } } の様に記述できる。 (edited)switch x { case 0: break case 1: print(y) print(z) default: print(y) print(z) } こういう複数のcaseを1行に書いたら構文エラーをレポートする。コンパイルはswiftcだからビルドはできる。独自Parserがあるんだな。Consecutive statements on a line must be separated by ';' になっちゃうと思いますが。case 1 の時に print(y);print(z) の動作ですか?case 1 見落としやすいので構文エラーにして欲しい感 is ある func foo() {} func bar() {} これも曖昧ではないけどエラーになるので、同じポリシーで行くべきだと思います。class A{}; protocol B {};とかはセミコロン必要ですよね。if value==1 {}はOKだけどif velue!=1 {}これがダメなのは理解できるけどわかりにくいから演算子は全部スペース必要でいいんじゃないかと思ったりしてます。0..<(n*2) (edited)...や..<と変わるのが微妙そうですね0 ..< 3 と..<3で違うスペースの入れ方が強制されるのは微妙だなと..<3 は許されるのに 1..<3 が許されないのは揃ってないということか..< 3が許されてないのはいいんかという話にもなりかねませんがprotocol A { associatedtype B associatedtype C where C == B.Hoge } struct D: A { typealias B = String typealias C = String }
where C == B.Hoge のHogeという型がBに無いのにコンパイルが通ってしまった。where句の制約は無視されるようになってしまいましたprotocol HasHoge { associatedtype Hoge } protocol A { associatedtype B: HasHoge associatedtype C where C == B.Hoge } struct D: A { typealias B = String typealias C = String } 健全な形はこうか。B.Hoge って書いてある時点でエラーになりそうなのに確かに通るねSomeType: SomeProtocol みたいなジェネリクスはもちろん必要だけど、逆に SomeType: !SomeProtocol みたいなジェネリクスも地味に欲しいよな…<T: FooEnum> where T != case .foo> みたいなこともしたい・・・。case の一部を禁じたいこと多い。enum じゃなくて sealed class で) (edited)public class Holder<T> {} extension Holder { public func ho() { print("ho1") } } extension Holder where T == String { @available(*, unavailable) public func ho() { print("ho2") } } let a = Holder<Int>() a.ho() // これでいけるかと思ったら ho1 が出力された・・・ let b = Holder<String>() b.ho() 作戦失敗 (edited)enum NetworkError: Error { case timedOut case cannotFindHost case notConnectedToInternet } enum MyAPIError: NetworkError { case responseInvalid case sessionExpired case notEnoughMinerals case insufficientVespineGas } (edited)case を追加できちゃわない?: NetworkError だけど、 NetworkError として扱えるわけではない?? (edited)enum Foo: Int は Int に入れられるわけじゃないからいいのかな?: Foo に新たな概念を追加することになるのか・・・。enum MyAPIError { spread case NetworkError case responseInvalid case sessionExpired case notEnoughMinerals case insufficientVespineGas } ↑こんな記法だったら良さそう。 (edited)T: !Optional ですねwT: !Optional
fun <T: Any> foo() (edited)// 親?クラス struct Animal { var name: String func speak() -> String { return "I am \(name)" } } // トリックここから protocol AnimalExtend { var animal: Animal { get set } var name: String { get set } func speak() -> String } extension AnimalExtend { var name: String { get { return animal.name } set { animal.name = newValue } } func speak() -> String { return animal.speak() } } // トリックここまで // ユーザー例 // プロトコル指定は継承指示 struct Cat : AnimalExtend { // コンパイルエラーがでるのでこれを定義 var animal: Animal // 必然的にこれも書くことになる init(name: String) { animal = Animal(name: name) } } print(Cat(name: "tama").speak()) // okAny? がトップタイプですからねぇ。 Any で縛れば nullable を弾けますが、 Swift の Optional は union じゃないから同じことはできないんですよねぇ。Optional<Optional<T>> ができるのは魅力的ですがOptional のネストはほしいですね。つい最近もやっぱいるよなと思ったけど何だったかな・・・。struct の継承もほしい。struct Path: String { // パス操作のための便利メソッド }Path を型として分離できるし、 String として使いたいときはそのまま代入できる。transparent struct Path: String { } みたいな。 (edited)Path is String であるためには。let s: String = path ができたい。func asString() -> String が 自動で is や as で呼び出されれば大丈夫String is Path も取りたいなら駄目ですけどねString is Path だと意味がない。Path のところに String 渡せてしまうから。.asString() で。Path はあくまで String なんだけど、 Path として扱っているときは String を突っ込まれたくない。String に Path は入れたいけど Path に String は入れたくない。typealias Path = String だと Path に String を突っ込めてしまうけどString を引数にとる関数に Path を渡すときにいちいち変換したくない。String と Path で話してるからわかりづらいのかも。struct Age: Int {}Age と Int とかWeight: Int と Height: Int から BMI 計算するときにprotocol IntConvertible { func asInt() -> Int } extension Age : IntConvertible {} こうしておいて、X: IntConvertibleで受ければFloat と Double はメモリレイアウトが違うし別の型だけどAge は Int の用途を絞りたいだけだから、Age is Int は OK だと思うんよね。Float とかにするわけでしょ?struct Weight { let value: Float } とか作って区別するっていうならわかるけど。typealias TimeInterval = Double じゃない?独自に作ったってこと?Float にアップキャストされない方がいいような気もしてきた。1999年、NASAの火星探査衛星マーズ・クライメート・オービターは、制御プログラムの力の単位にポンド重とニュートンが混在していたために、計画よりはるかに低い軌道に投入されてしまい、火星大気との摩擦により墜落してして失われてしまいました。単位計算のルールを型システムにエンコードできれば、コンパイル時にすべての単位エラーを検出できるはずです。enum と同じように、 struct Path: String したら、 path.rawValue で String が得られるとかでいいのかも?わざわざ構文増やさなくても、↓書けばいいだけかな・・・。 struct Path { let rawValue: String }public init の実装必須のはず。 (edited): String の意味はあるか?dispatch_once で検索すると出てくる let myGlobal = { … global contains initialization in a call to a closure … }() _ = myGlobal // using myGlobal will invoke the initialization code only the first time it is used.JSONEncoderとJSONDecoder互換のクラスを追加してみた。 https://github.com/norio-nomura/ObjectEncoder/pull/18JSONSerializationへ渡す/から受け取るobjectをエンコード/デコードしてる。classの場合 のコードがうごくのはおかしいよねっとw https://qiita.com/noppefoxwolf/items/a9d2a103d54b2b1ea415class でも self を書き換え可能な mutating func がほしいなぁと感じてます。static func で違う Self 返すしかないですねFoo に対して func update(foo: Foo, ...) -> Foo { ... } と class Foo { func update(...) -> Foo { ... } } があって、 (edited)var foo = ... foo = update(foo: foo, ...) foo = foo.update(...) と書くのをclass User: Initializable { var id: Int = 1000 /* 暗黙の */ init() {} } extension Initializable { init() { self = Factory.make(type: Self.self) } } User() で、暗黙の User.init() に直接ディスパッチされていると思います。 (edited)func update(foo: inout Foo, ...) { ... } のように inout にして update(foo: &foo, ...) はできるけど、 mutating func がないので対応するメソッド版 update を作れないです。mutating func は self を inout に持つ関数という文脈で)Account の id の初期値をなくすと、それもそのままコンパイルできちゃってStackOverflowになりますinit(id: Int) になるので Initializable.init() と Factory.make(type:) で無限再帰ですね。@tarunon さん、 @rintaro さんと @omochimetaru さんと議論して パワーワードだwfunc bar() { foo() } func foo() { bar() } (edited)@_transparent つけると、先に展開されてからの検知になるので、警告してくれましたが。func generate() -> UInt32 { let a = arc4random_uniform(10) if a > 10 { return a } else { return generate() } }func generate() -> UInt32 { let a = arc4random() % 10 if a > 10 { return a } else { return generate() } }$ swift Welcome to Apple Swift version 4.1 (swiftlang-902.0.43 clang-902.0.37.1). Type :help for assistance. 1> Optional(1).map(dump) error: repl.swift:1:17: error: ambiguous reference to member 'dump(_:to:name:indent:maxDepth:maxItems:)' Optional(1).map(dump) ^~~~ (edited) 1> :type lookup dump @discardableResult @_inlineable @_semantics("optimize.sil.specialize.generic.never") func dump<T>(_ value: T, name: Swift.String? = default, indent: Swift.Int = default, maxDepth: Swift.Int = default, maxItems: Swift.Int = default) -> T @discardableResult @_inlineable @_semantics("optimize.sil.specialize.generic.never") func dump<T, TargetStream>(_ value: T, to target: inout TargetStream, name: Swift.String? = default, indent: Swift.Int = default, maxDepth: Swift.Int = default, maxItems: Swift.Int = default) -> T where TargetStream : TextOutputStream#lineとか使っててマクロがないSwiftでは詰むfunc dump<T>(name: String?=nil, indent: Int=0, maxDepth: Int=0, maxItems: Int=0) -> (T) -> Void { return { value in dump(value, name: name, indent: indent, maxDepth: maxDepth, maxItems: maxItems) } } (Int?.none).map(dump())f(a, b, c, d) に対して 好きな引数を埋めた関数を得る操作があると便利か?extension Array { func mapSpecialized<U>(_ type: U.Type=U.self) -> ((Element) -> U) -> [U] { return { self.map($0) } } } こういうの作るとmapを取り回せるようになるvar a = [2, 3, 5] var b = a a.withUnsafeMutableBufferPointer { $0.baseAddress!.pointee = -1 } print(a) // [-1, 3, 5] print(b) // [2, 3, 5]
var a = [2, 3, 5] var b = a a.withUnsafeBufferPointer { UnsafeMutablePointer(mutating: $0.baseAddress!).pointee = -1 } print(a) // [-1, 3, 5] print(b) // [-1, 3, 5]withUnsafeMutable~~は実行した瞬間コピーされてるんですかね? 中身で書き換えるかどうかまで判断してたら相当賢そうですけどwithUnsafeBufferPointer 使えばいいわけだし問題はなさそう。UnsafeMutablePointer の pointee に参照型のインスタンス set するとリファレンスカウント増える??増えないと思ってた。 extension Array { mutating func update(_ body: (inout Element) throws -> ()) rethrows { let count = self.count try withUnsafeMutableBufferPointer { var pointer = $0.baseAddress! for _ in 0..<count { try body(&pointer.pointee) pointer += 1 } } } } class Cat { let name: String init(_ name: String) { self.name = name } deinit { print("deinit: \(name)") } } var a = [Cat("a"), Cat("b"), Cat("c")] a.update { $0 = Cat("\($0.name)2") }
deinit: a deinit: b deinit: cUnsafeRawPointer としてコピーとかすると壊れるのか。update は問題なさそうだけど、これより速い実装ってあるかな?count が無駄かと思ってポインタを比較してループ回してたけどDispatchQueue.concurrentPerformを使ったconcurrentUpdateとか。extension Array { mutating func update(_ body: (inout Element) throws -> ()) rethrows { let count = self.count try withUnsafeMutableBufferPointer { var pointer = $0.baseAddress! let end = pointer + count while pointer != end { try body(&pointer.pointee) pointer += 1 } } } }getBase() ..< getBase() + count を getBase() 一回で綺麗に書く構文って現状ありましたっけ? for pointer in $0.baseAddress! ..< $0.baseAddress! + count { try body(&pointer.pointee) } をもっと短く書きたい。string[string.index(string.startIndex, offsetBy: 3) ..< string.index(string.startIndex, offestBy: 6)] これも短く書きたい (edited)string[offset: 3..<6] の議論はどんな感じなんだっけな。$0.baseAddress! ..< $0.baseAddress! + count できるの知らなかったーinfix operator ~> : StridePrecedence prefix operator ~> infix operator ~>- : StridePrecedence prefix operator ~>- infix operator ...~> infix operator ...~>-public func ~>-(range: CountableRange<Int>, stride: Int) -> NDArrayIndexElement { return range ~> (-stride) }a~>-b は a ~> (-b) なのねoperator の上書きが出来ることを初めて知った。 ~> は stdlib で既に定義されているので、:soon: 入れると勝手に brew tap el-hoshino/zundoko brew install zundoko そして使い方は zundoko の後に適当に何か英文章書きます、何が出力されるかはEnter押してからのお楽しみw zundoko try! Swift is Good! a...swiftc --emit-silと書いてしまうjava -version さんパターンだ--version になるよみたいな話を観た気がしてウキウキして java 9 いれて --version してそんなオプションネーヨと言われた気持ち
1do try 文だとネストが深くなるから、guard try let error {as XxxError} 文欲しくなった今日の今頃guard try? else と同じような挙動で、guard と同じ階層で正常系を描く処理ですね、ただ guard try? は error を消すけどこちらは消さないguard let player = try AVAudioPlayer(name: name) catch let error as NSError { print(error) // エラーハンドリング return } catch let error { return } player.play() みたいな (edited)do { try ... } catch { print(error) // エラーハンドリング return }do の中で書くとネストが深くなるのがちょっと微妙に嫌ですねguard let Type = Type? も guard let Type = try Type も同じようなものだと思うんですよね、どちらも「確実な Type が欲しい」というわけで-plistArg '{"foo" = bar; "array" = ("foo", {"bar" = "baz"; } ); }' と -xmlArg "<dict><key>foo</key><string>bar </string><key>baz</key><string>qux</string></dict>" をフォーマットを事前に指定することもなく、両方使えるようにするとか普通に考えておかしいなあと。protocol HasCodingKeys: Codable {} extension HasCodingKeys { func encode(to encoder: Encoder) throws { fatalError() } init(from decoder: Decoder) throws { fatalError() } } struct A: HasCodingKeys { private typealias Keys = CodingKeys // Use of undeclared type 'CodingKeys' }
Codable の init(from decoder: Decoder) とfunc encode(to encoder: Encoder) をprotocol extensionに実装すると、Aの中でCodingKeys がundeclaredになるんですが、どういう仕組みになってるんですかね。 (edited)struct A: HasCodingKeys { typealias Keys = CodingKey }struct A: Codable { struct B {} let b: B typealias Keys = CodingKeys } これを通したかったみたいでした。 (edited)@available(*, unavailable)って出来ない?setterだけじゃなくgetterの場合もなんですよね。 以前subscriptのsetterだけ定義したくて試してだめだったのでvar _x: Int = 0 var x: Int { @available(*, unavailable) get { return _x } @available(*, unavailable) set { _x = newValue } } print(x) // 0 x = 100 print(_x) // 100 (edited)@availableだけの話では無いですよね。private(get)も無いから。subscriptやプロパティである必要がない、ってことなのではないかと思います。 (edited)private var privateValue = 0 func setValue(_ value: Int) { privateValue = value }deprecated は実装されそう。 (edited)foo.bar.baz = 1 で、foo の getter の方が絞られていると bar がそもそも取り出せないので、変な感じになってくるとかはありそうですね。
(edited)setHogehoge(~)があってgetHogehoge()がないのはそこまで違和感を覚えないimport XCTest @testable import pow let lhs = 10 let rhs = 10 let count = 1000000 let expect = Int(pow(Double(lhs), Double(rhs))) final class powTests: XCTestCase { func test0() { var x: Int = 0 measure { for _ in 0..<count { x = power0(lhs, rhs) } } XCTAssertEqual(x, expect) } …expectの算出に使ってるInt(pow(Double(lhs), Double(rhs)))の速度も測ろうと考え func test_() { var x: Int = 0 measure { for _ in 0..<count { x = Int(pow(Double(lhs), Double(rhs))) } } XCTAssertEqual(x, expect) } を追加したら、10000倍くらい速かった。x = expectに書き換えてただけだった…pow が参照等価であることをどうやって知ってるんですか?let expect = Int(pow(Double(lhs), Double(rhs)))ってのがあって、テストtest_()内でそのexpectを参照してるのと、Int(pow(Double(lhs), Double(rhs)を別モジュールの関数にした場合と速度差がありすぎることから、x = expectにしているという僕の推測です。 (edited)test_()内のループカウンタをどれだけ増やしても実行時間が変わらないので、ループ自体が無くなってるのかも?@inline(never) public func blackHole<T>(_ x: T) {} に食わせて、最適化を防いでますね。 measure { for _ in 0..<count { blackHole(Int(pow(Double(lhs), Double(rhs)))) } }x = expect になってるんだったら blackHole(expect) になるだけだから防げないか。 (edited)echo 'import Foundation; let lhs = 10, rhs = 9, count = 10000000, expect = Int(pow(Double(lhs), Double(rhs))); func test() { var x: Int = 0; for _ in 0..<count { x = Int(pow(Double(lhs), Double(rhs))) }; print(x == expect) }; test()'|swiftc -emit-assembly - -O|xcrun swift-demangle (edited)powの呼び出し自体がなくなってるぽい。-Ononeにするとcallq _powが2箇所現れる。x = expectにしてるわけでは無く、コンパイル時に定数になってるぽい。 movq $10, _main.lhs : Swift.Int(%rip) movq $9, _main.rhs : Swift.Int(%rip) movq $10000000, _main.count : Swift.Int(%rip) movq $1000000000, _main.expect : Swift.Int(%rip) callq _main.test() -> () (edited)powの呼び出しが残ってる。@llvm.pow.f64 に置き変えですか? (edited)-emit-irでpowは無くなって定数1000000000になってますね。 define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 { entry: store i64 10, i64* getelementptr inbounds (%TSi, %TSi* @main.lhs : Swift.Int, i64 0, i32 0), align 8 store i64 9, i64* getelementptr inbounds (%TSi, %TSi* @main.rhs : Swift.Int, i64 0, i32 0), align 8 store i64 10000000, i64* getelementptr inbounds (%TSi, %TSi* @main.count : Swift.Int, i64 0, i32 0), align 8 store i64 1000000000, i64* getelementptr inbounds (%TSi, %TSi* @main.expect : Swift.Int, i64 0, i32 0), align 8 tail call swiftcc void @main.test() -> ()() ret i32 0 }emit-ir はLLVM最適化後でした。 https://twitter.com/rintaro/status/963754184494350336-disable-llvm-optzns をフロントエンドに渡してあげると見えるかもしれない。$ echo 'import Foundation; let lhs = 10, rhs = 9, count = 10000000, expect = Int(pow(Double(lhs), Double(rhs))); func test() { var x: Int = 0; for _ in 0..<count { x = Int(pow(Double(lhs), Double(rhs))) }; print(x == expect) }; test()'|swiftc -frontend -emit-ir -primary-file - -target x86_64-apple-darwin17.4.0 -enable-objc-interop -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk -O -color-diagnostics -disable-llvm-optzns -module-name main -o - |xcrun swift-demangle$ echo 'import Foundation; let lhs = 10, rhs = 9, count = 10000000, expect = Int(pow(Double(lhs), Double(rhs))); func test() { var x: Int = 0; for _ in 0..<count { x = Int(pow(Double(lhs), Double(rhs))) }; print(x == expect) }; test()' | swiftc -O -emit-ir -Xfrontend -disable-llvm-optzns -define i32 @main(i32, i8**) #0 { entry: %2 = bitcast i8** %1 to i8* store i64 10, i64* getelementptr inbounds (%TSi, %TSi* @main.lhs : Swift.Int, i32 0, i32 0), align 8 store i64 9, i64* getelementptr inbounds (%TSi, %TSi* @main.rhs : Swift.Int, i32 0, i32 0), align 8 store i64 10000000, i64* getelementptr inbounds (%TSi, %TSi* @main.count : Swift.Int, i32 0, i32 0), align 8 %3 = call double @pow(double 1.000000e+01, double 9.000000e+00)
pow残ってる。define i32 @main(i32, i8**) #0 { entry: %2 = bitcast i8** %1 to i8* store i64 10, i64* getelementptr inbounds (%TSi, %TSi* @_T04main3lhsSivp, i32 0, i32 0), align 8 store i64 9, i64* getelementptr inbounds (%TSi, %TSi* @_T04main3rhsSivp, i32 0, i32 0), align 8 store i64 10000000, i64* getelementptr inbounds (%TSi, %TSi* @_T04main5countSivp, i32 0, i32 0), align 8 %3 = call double @pow(double 1.000000e+01, double 9.000000e+00) %4 = bitcast double %3 to i64 ... declare double @pow(double, double) #1 この時点ではまだ 普通のpowですね。powは単純なforループ版より3~9倍遅かった。x = expect にしているという僕の推測です。 pow が参照等価であることをコンパイラが知らないと x = expect とすることができないんじゃないかと思ったんですが、そもそもコンパイル時に展開されているということは pow が特別扱いされてそうですね。
/// canConstantFoldCallTo - Return true if its even possible to fold a call to /// the specified function. bool canConstantFoldCallTo(ImmutableCallSite CS, const Function *F);canConstantFoldCallToの実装。 https://github.com/apple/swift-llvm/blob/stable/lib/Analysis/ConstantFolding.cpp#L1441switch のパターンマッチに ? 使えるの知らなかったif case let だけかと思ってた。 let a: Int? = 42 switch a { case let x?: print(x + 1) // 43 default: print("nil") }.some(let x) って書いてた。.some(let x) にしてた。x?. の時は ?. だけど x?: の時は x? : なのが紛らわしいな。: は演算子には使えない文字なんだっけ。switch (open, close) { case (let open?, let close?): return "\(open)〜\(close)" case (let open?, nil): return "\(open)〜" case (nil, let close?): return "〜\(close)" case (nil, nil): return "" } 最近こんなん書いたけど、?ついてるからややこしいなーと (edited).some の方が可読性高い?? ついてると一瞬脳が Optional と認識してしまいそうかも?if case let a? = aOrNil はうまい表現だと思うんだよなぁ。宣言しているのはあくまで a で ? が剥がされてる感が。if let a? = aOrNil にしてほしい。else ifでかかなきゃならない?if case の1行表記が欲しいenum Animal { case cat(Cat) case dog ... } ↑で animal: Animal から Cat? を取り出したい (edited)run { if case .cat(let x) = animal { return x } else { return nil } } (edited)Cat? を取り出しても、大抵のケースでは結局その後で分岐することになるのでは?button.isEnabled = ... みたいなときに Bool がほしいのはある気がする。Observable<Animal> から Observable<Cat>` に変換する時とかにほしいんですよArray<Animal> から Array<Cat> に compactMap するとかでもいいですね。switch か if case して return するしかなさそうだなぁ。 (edited)'public' modifier cannot be used with extensions that declare protocol conformances と言われるんですが、なぜそうなってるんでしょう?(でも外からはちゃんと認識されてるっぽい)extension Polynomial: EuclideanRing where R: Field {protocol Collection: Sequence みたいに書くのとはまた違う感じでしょうか?func bar(foo: int) { func inner(arg: int = foo) {} print(inner()) } bar(foo: 3)Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnu/usercode/main.swift:1:15: error: use of undeclared type 'int' func bar(foo: int) { ^~~ /usercode/main.swift:2:21: error: use of undeclared type 'int' func inner(arg: int = foo) {} ^~~func bar(foo: Int) { func inner(arg: Int = foo) {} print(inner()) } bar(foo: 3)Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnuswift: /home/buildnode/jenkins/workspace/oss-swift-4.1-package-linux-ubuntu-16_04/swift/lib/SILGen/SILGenGlobalVariable.cpp:64: bool isGlobalLazilyInitialized(swift::VarDecl *): Assertion `!var->getDeclContext()->isLocalContext() && "not a global variable!"' failed. /usr/bin/swift[0x3f24d54] /usr/bin/swift[0x3f25096] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f15d2b98390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7f15d12d7428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7f15d12d902a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7f15d12cfbd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7f15d12cfc82] /usr/bin/swift[0xc929db] /usr/bin/swift[0xc6a1e3] /usr/bin/swift[0xc6af00] /usr/bin/swift[0xc7448c] /usr/bin/swift[0xc69ee4] /usr/bin/swift[0xcc47f6] /usr/bin/swift[0xc91f8d] /usr/bin/swift[0xc2e86b] /usr/bin/swift[0xc2c51b] /usr/bin/swift[0xc2b847] /usr/bin/swift[0xcc1225] /usr/bin/swift[0xcc106e] /usr/bin/swift[0xc8fec5] /usr/bin/swift[0xc33515] /usr/bin/swift[0xc2ba85] /usr/bin/swift[0xc30f7b] /usr/bin/swift[0xc31c46] /usr/bin/swift[0xc3221d] /usr/bin/swift[0x4c27c4] /usr/bin/swift[0x4beecc] /usr/bin/swift[0x4778c4] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f15d12c2830] /usr/bin/swift[0x475179] Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret /usercode/main.swift -disable-objc-interop -module-name main 1. While emitting SIL for 'bar(foo:)' at /usercode/main.swift:1:1 2. While silgen emitFunction SIL function "@_T04main3barySi3foo_tF". for 'bar(foo:)' at /usercode/main.swift:1:1 3. While silgen emitDefaultArgGenerator SIL function "@_T04main3barySi3foo_tF5innerL_ySi3arg_tFfA_". for expression at [/usercode/main.swift:2:27 - line:2:27] RangeText="f" Aborted (core dumped)Assertion !var->getDeclContext()->isLocalContext() && "not a global variable!"' failed. (edited)struct Stone {} extension Stone { func aaa<T>(_ t: T) {} }protocol A {} protocol B {} protocol C {} extension A: B where Self: C {} extension B: C where Self: A {} extension C: A where Self: B {}2018-03-31-a 4.1 4.0.3 3.1.1 3.0.2func bar(foo: Int) { func inner(arg: Int = foo) {} print(inner()) } bar(foo: 3)Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnuswift: /home/buildnode/jenkins/workspace/oss-swift-4.1-package-linux-ubuntu-16_04/swift/lib/SILGen/SILGenGlobalVariable.cpp:64: bool isGlobalLazilyInitialized(swift::VarDecl *): Assertion `!var->getDeclContext()->isLocalContext() && "not a global variable!"' failed. /usr/bin/swift[0x3f24d54] /usr/bin/swift[0x3f25096] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f6befe6f390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7f6bee5ae428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7f6bee5b002a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7f6bee5a6bd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7f6bee5a6c82] /usr/bin/swift[0xc929db] /usr/bin/swift[0xc6a1e3] /usr/bin/swift[0xc6af00] /usr/bin/swift[0xc7448c] /usr/bin/swift[0xc69ee4] /usr/bin/swift[0xcc47f6] /usr/bin/swift[0xc91f8d] /usr/bin/swift[0xc2e86b] /usr/bin/swift[0xc2c51b] /usr/bin/swift[0xc2b847] /usr/bin/swift[0xcc1225] /usr/bin/swift[0xcc106e] /usr/bin/swift[0xc8fec5] /usr/bin/swift[0xc33515] /usr/bin/swift[0xc2ba85] /usr/bin/swift[0xc30f7b] /usr/bin/swift[0xc31c46] /usr/bin/swift[0xc3221d] /usr/bin/swift[0x4c27c4] /usr/bin/swift[0x4beecc] /usr/bin/swift[0x4778c4] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f6bee599830] /usr/bin/swift[0x475179] Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret /usercode/main.swift -disable-objc-interop -module-name main 1. While emitting SIL for 'bar(foo:)' at /usercode/main.swift:1:1 2. While silgen emitFunction SIL function "@_T04main3barySi3foo_tF". for 'bar(foo:)' at /usercode/main.swift:1:1 3. While silgen emitDefaultArgGenerator SIL function "@_T04main3barySi3foo_tF5innerL_ySi3arg_tFfA_". for expression at [/usercode/main.swift:2:27 - line:2:27] RangeText="f" Aborted (core dumped)func bar(foo: Int) { func inner(arg: Int = foo) {} print(inner()) } bar(foo: 3)Swift version 4.2-dev (LLVM 0d52728a8a, Clang 1d3cad1e6b, Swift 6c42bcccbd) Target: x86_64-unknown-linux-gnuswift: /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-16_04/swift/lib/SILGen/SILGenGlobalVariable.cpp:64: bool isGlobalLazilyInitialized(swift::VarDecl *): Assertion `!var->getDeclContext()->isLocalContext() && "not a global variable!"' failed. /usr/bin/swift[0x411c854] /usr/bin/swift[0x411cb96] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f64a8588390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7f64a6cc7428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7f64a6cc902a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7f64a6cbfbd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7f64a6cbfc82] /usr/bin/swift[0xcb8bb3] /usr/bin/swift[0xc8d123] /usr/bin/swift[0xc8dde3] /usr/bin/swift[0xc9e360] /usr/bin/swift[0xc8cef4] /usr/bin/swift[0xcecb34] /usr/bin/swift[0xcb8091] /usr/bin/swift[0xc4fb59] /usr/bin/swift[0xc4d64f] /usr/bin/swift[0xc4c878] /usr/bin/swift[0xce96b5] /usr/bin/swift[0xce94fe] /usr/bin/swift[0xcb5f5b] /usr/bin/swift[0xc54c84] /usr/bin/swift[0xc4cb25] /usr/bin/swift[0xc525bb] /usr/bin/swift[0xc53266] /usr/bin/swift[0xc5385d] /usr/bin/swift[0x4d820d] /usr/bin/swift[0x4d4b9c] /usr/bin/swift[0x48a26d] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f64a6cb2830] /usr/bin/swift[0x487ac9] Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret /usercode/main.swift -disable-objc-interop -module-name main 1. While emitting SIL for 'bar(foo:)' at /usercode/main.swift:1:1 2. While silgen emitFunction SIL function "@$S4main3bar3fooySi_tF". for 'bar(foo:)' at /usercode/main.swift:1:1 3. While silgen emitDefaultArgGenerator SIL function "@$S4main3bar3fooySi_tF5innerL_3argySi_tFfA_". for expression at [/usercode/main.swift:2:27 - line:2:27] RangeText="f" Aborted (core dumped)func foo<T>(_ array: [T?]) -> [T] { ... } はできるのに↓ができないのは、関数よりもメソッドを優先する Swift としては明らかな言語仕様的不足。 extension<T> Array where Wrapped == T? { func foo() -> [T] { ... } }OptionalProtocol 、昔は where T == Int? とかでも必要だったけどこれは解消してマシになったんですけど、まだ == T? が書けないんですよねぇ。compactMap の Proposal に書かれてる compact も実装できない・・・。 https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.mdextension<T> Array where Element == T? { func foo() -> [T] { ... } } (edited)extension Array where Element: OptionalConvertible { ... } extension Optional : OptionalConvertble { ... } (edited)public protocol OptionalConvertible { associatedtype _Wrapped func asOptional() -> Optional<_Wrapped> } extension Optional : OptionalConvertible { public func asOptional() -> Optional<Wrapped> { return self } }public protocol EquivalenceRelation { .. } public struct QuotientSet<X, Rel: EquivalenceRelation>: SetType where X == Rel.Base { .. } public struct ModSubgroupRelation<H: Subgroup>: EquivalenceRelation { .. } public typealias QuotientGroup<G, H: Subgroup> = QuotientSet<G, ModSubgroupRelation<H>> where G == H.Super extension QuotientGroup: Group where X: Group, Rel: ModSubgroupRelation<H> // あっprotocol A {} struct X<T: A> {} struct B<S>: A{} typealias Y<S> = X<B<S>> extension<S> Y where T == B<S> { .. } // コレ (edited)protocol A {} struct X<T: A> {} struct B<S>: A{} typealias Y<S> = X<B<S>> protocol BProtocol: A { associatedtype _S var bValue: B<_S> { get } } extension B : BProtocol { var bValue: B<S> { return self } } extension X where T : BProtocol { // これがやりたい }extension<S> Y where T == B<S> は extension<S> X where T == B<S> と同じ意味になると思います。Optional の話と合わせると BProtocol を BConvertible とした方がよかったかもしれません。BProtocl は B に変換できるので実質的に B のように扱えます。public protocol _ModSubgroupRelation: EquivalenceRelation where Base == Sub.Super { associatedtype Sub: Subgroup } public struct ModSubgroupRelation<H: Subgroup>: _ModSubgroupRelation { public typealias Base = H.Super public typealias Sub = H ... } public typealias QuotientGroup<G, H: Subgroup> = QuotientSet<G, ModSubgroupRelation<H>> where G == H.Super extension QuotientGroup: Group where Rel: _ModSubgroupRelation, X == Rel.Base { ... } できたっぽいです!_ModSubgroupRelation プロトコルから ModSubgroupRelation を取り出すメソッドかプロパティをつけないといけないと思います。 (edited)protocol P{} struct A<T> {} extension A: P where T == Int {} extension A: P where T == String {} // error: redundant conformance of 'A<T>' to protocol 'P' 異なる条件でも同じ protocol への conformance はできないんですね…protocol IntOrString {} extension Int: IntOrString {} extension String: IntOrString {} extension A: P where T: IntOrString {} みたいに回り道が必要になりますねぇ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' }Swift version 4.1 (swift-4.1-RELEASE)/usercode/main.swift:7:1: error: type 'X<T>' does not conform to protocol 'B' extension X: D where T == Int { // Type 'X<T>' does not conform to protocol 'B' ^ /usercode/main.swift:4:10: note: type 'X<T>' does not conform to inherited protocol 'B' protocol D: B, C {} ^protocol A {} protocol B: A {} protocol C: A {} protocol D: B, C {} struct X<T>: A{} extension X: B where T == Int {} extension X: C where T == Int {} extension X: D where T == Int {}Swift version 4.1 (swift-4.1-RELEASE)protocol A {} protocol B: A {} protocol C: A {} protocol D: B, C {} struct X<T>: A{} extension X: B, C, D where T == Int {}Swift version 4.1 (swift-4.1-RELEASE)extension BilinearMap: VectorSpace, BilinearMapType where Domain: ProductSetType & VectorSpace, Domain.Left: VectorSpace, Domain.Right: VectorSpace, Codomain: VectorSpace, Domain.CoeffRing == Codomain.CoeffRing, Domain.CoeffRing == Domain.Left.CoeffRing, Domain.CoeffRing == Domain.Right.CoeffRing {extension <V1: VectorSpace, V2: VectorSpace, W: VectorSpace> BilinearMap: BilinearMapType where Domain == ProductVectorSpace<V1, V2>, Domain.CoeffRing == Codomain.CoeffRing { } これで済むと思います。extension<T> Array where Element == Optional<T> { func compact() -> Array<T> { ... } } の代わりに func compact<T>(_ array: Array<Optional<T>>) -> Array<T> { ... } になりますが、関数だと記述順が辛いところをfunc |> (a, b) { return b(a) }public typealias BilinearForm<V: VectorSpace> = BilinearMap<V, V, AsVectorSpace<V.CoeffRing>> extension BilinearForm: BilinearFormType where Domain: ProductSetType & VectorSpace, Domain.Left: VectorSpace, Domain.Left == Domain.Right, Domain.CoeffRing == Domain.Left.CoeffRing, Codomain == AsVectorSpace<Domain.CoeffRing> { }typealias に対して extension を書かない方がいいかもしれませんね。class C<T> {} typealias IntC = C<Int> extension IntC {}Swift version 4.1 (swift-4.1-RELEASE)/usercode/main.swift:3:1: error: constrained extension must be declared on the unspecialized generic type 'C' with constraints specified by a 'where' clause extension IntC {} ^ ~~~~ #if swift(>=4.1.0) let version = "4.1.0" #elsif swift(>=4.0.3) // it should be `elseif` let version = "4.0.3" #endifSwift version 4.1 (swift-4.1-RELEASE)/usercode/main.swift:3:9: error: expected expression #elsif swift(>=4.0.3) // it should be `elseif` ^ /usercode/main.swift:4:17: error: invalid redeclaration of 'version' let version = "4.0.3" ^ /usercode/main.swift:2:17: note: 'version' previously declared here let version = "4.1.0" ^ #if swift(>=4.1.0) let version = "4.1.0" #elsif swift(>=4.0.3) // it should be `elseif` let version = "4.0.3" #endifSwift version 4.1 (swift-4.1-RELEASE)error: failed to launch REPL process: process launch failed: 'A' packet returned an error: 8 #if swift(>=4.1.0) let version = "4.1.0" #elsif swift(>=4.0.3) // it should be `elseif` let version = "4.0.3" #endifSwift version 4.1 (swift-4.1-RELEASE)-swift-version 3が付いた時に#elsifってのがそのまま通ってしまうぽい?#if から #endif の間が swift(>=4.1.0) じゃないので、パースの対象外になるので、_ = version書いとけば判定はできそうですね。 一般的には使えなそうですが。-swift-version 3 でも 4.2 対応のコンパイラなら swift(>=4.1.0) は false だけども内容はパースする。canImport()とかの新しい条件が含まれてた時にエラーになったりしないですかね。つまり -swift-version 3 でも 4.2 対応のコンパイラなら swift(>=4.1.0) は false だけども内容はパースする。 コードが想定する対応バージョンのコンパイラでちゃんとテストしろ、で済んでしまう問題ではあるのですよね…extension Optional { public func unwrap(_ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) -> Wrapped { guard let value = self else { let m = message() fatalError("Optional unwrap failed" + (!m.isEmpty ? ": " + m : ""), file: file, line: line) } return value }guard let tableView = tableViewController.tableView else { fatalError("UITableViewControllerじゃなくなった?") }let tableView = tableViewController.tableView.unwrap("UITableViewControllerじゃなくなった?") ↑こうかいたほうがよくない?!とか、死ぬケースっていうのは、把握しておく必要はないはずなんだよね!相当のクラッシュとかは、メソッド冒頭に集めてあるイメージではあるfunc preconditionNotNone<T>(_ t: T?) -> T let x = a.x * b.x - a.y * b.y - a.z * b.z - a.w * b.w が Expression was too complex... と言われて辛いlet x = a.x * b.x - (a.y * b.y + a.z * b.z + a.w * b.w)true && true && true とかやるだけで出てた気がするのでだいぶ良くはなったんだと思いますがx, y, z, w の型が定まってるなら組み合わせなさそうですけどねーExpressibleByXxxLiteral で組み合わせ爆発するけど(ここが Swift 特有の問題だと思ってます)、この場合はどうしてだろう・・・。 (edited)Double ? public static func -(a: 𝐑, b: 𝐑) -> 𝐑 { return 𝐑(a.value - b.value, a.error + b.error) }(a.x * b.x )- (a.y * b.y) - (a.z * b.z) - (a.w * b.w) の - を探し続けてたってこと? (edited)swift -frontend -typecheck -debug-constraints ファイル名.swift で見れます )public extension AdditiveGroup { public static func -(a: Self, b: Self) -> Self { return (a + (-b)) } }
https://github.com/taketo1024/SwiftyMath/blob/master/Sources/SwiftyMath/Abstract/AdditiveGroup.swift#L12let x = a.x * b.x + -a.y * b.y - a.z * b.z - a.w * b.wswift -frontend -typecheck -debug-constraints って簡単なコードでもすごい大量の出力がありますね。protocol FooProtocol { static func +(lhs: Self, rhs: Self) -> Self static func -(lhs: Self, rhs: Self) -> Self static prefix func-(value: Self) -> Self } extension FooProtocol { static func -(lhs: Self, rhs: Self) -> Self { return lhs + -rhs } } struct Foo : FooProtocol { static func +(lhs: Foo, rhs: Foo) -> Foo { return lhs } static prefix func-(value: Foo) -> Foo { return value } } let a = Foo() let b = a + a - a + a - a + a - a + aprotocol FooProtocol { static func +(lhs: Self, rhs: Self) -> Self static func -(lhs: Self, rhs: Self) -> Self static prefix func-(value: Self) -> Self } extension FooProtocol { static func -(lhs: Self, rhs: Self) -> Self { return lhs + -rhs } } struct Foo : FooProtocol { static func +(lhs: Foo, rhs: Foo) -> Foo { return lhs } static prefix func-(value: Foo) -> Foo { return value } } let a = Foo() let b = a + a - a + a - a + a - a + aprotocol FooProtocol { static func +(lhs: Self, rhs: Self) -> Self static func -(lhs: Self, rhs: Self) -> Self static prefix func-(value: Self) -> Self } extension FooProtocol { static func -(lhs: Self, rhs: Self) -> Self { return lhs + -rhs } } struct Foo : FooProtocol { static func +(lhs: Foo, rhs: Foo) -> Foo { return lhs } static prefix func-(value: Foo) -> Foo { return value } } extension Foo { static func -(lhs: Foo, rhs: Foo) -> Foo { return lhs + -rhs } } let a = Foo() let b = a + a - a + a - a + a - a + a- はデフォルト実装だからじゃないですか?prefix の可能性もあるのか。prefix と解釈したらパースに失敗しそうな?+ か - かどっちかは明示的な実装が必要でないですか?let x = a.x * b.x - a.y * b.y - a.z * b.z// - a.w * b.wprotocol FooProtocol { static func +(lhs: Self, rhs: Self) -> Self static func -(lhs: Self, rhs: Self) -> Self } extension FooProtocol { static func -(lhs: Self, rhs: Self) -> Self { return lhs + rhs } } struct Foo : FooProtocol { static func +(lhs: Foo, rhs: Foo) -> Foo { return lhs } } let a = Foo() let b = a + a - a + a - a + a - a + a@availableを使える様にしてもらった。 https://bugs.swift.org/browse/SR-7201.app 形式にうまくパッケージされない気が@testable import MainApp したらMainApp側の型がコード補完上見れるようになったところまではやったEXCLUDED_SOURCE_FILE_NAMES=AppDelegate.swift と書きつつ、 TestAppDelegate.swift というのだけ追加すればいいのではないかしら。 (edited)let viewController = ... let window = UIWindow() window.backgroundColor = .white window.rootViewController = viewController window.makeKeyAndVisible() RunLoop.main.run(until: Date(timeIntervalSinceNow: 0)) viewController.view.layer.render() ^ みたいなことをした方が簡単。Processで起動した子プロセスの出力をキャプチャする際にはDispatchGroupで待つと良いという知見を得た。 https://github.com/norio-nomura/SwiftCompilerDiscordappBot/blob/master/Sources/SwiftCompilerDiscordappBot/execute().swift#L27-L31dequeueReusableCell(withReuseIdentifier:for:)でインスタンス化を行うため、そもそもコンストラクタのカスタマイズはできないものなのでしょうか?let cell = collectionView.dequeueReusableCell(with: FilterCell.self, for: indexPath) cell.configure(image: image, name: name) 内包する案もよさそうですね、ありがとうございます*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the cell returned from -collectionView:cellForItemAtIndexPath: does not have a reuseIdentifier - cells must be retrieved by calling -dequeueReusableCellWithReuseIdentifier:forIndexPath:'message2でだけas [String : Any]が必要だと言われるのだろう? @swift-4.1.3
let content = "" let fields = [["name": "stdout.txt", "value": ""]] let message1 = fields.isEmpty ? ["content": content] : ["content": content, "embed": ["fields": fields]] let message2 = ["content": content, "embed": ["fields": fields]]main.swift:4:16: error: heterogeneous collection literal could only be inferred to '[String : Any]'; add explicit type annotation if this is intentional let message2 = ["content": content, "embed": ["fields": fields]] ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ as [String : Any]message1も同じ型になるのに。dynamicMemberLookup 把握。subscript(dynamicMember:)の実装を必要とするアトリビュートなんだね。 @swift-4.2.4
@dynamicMemberLookup indirect enum UID: CustomStringConvertible { case root(String) case leaf(parent: UID, String) subscript(dynamicMember member: String) -> UID { return .leaf(parent: self, member) } var description: String { switch self { case .root(let string): return string case .leaf(let parant, let string): return "\(parant).\(string)" } } } let root = UID.root("root") print(root.a.b.c)extension Matrix: Codable where R: Codable { //Implementation of 'Decodable' cannot be automatically synthesized in an extensionstruct を作れば解決する気がします。Array も Element が Codable なときだけ Codable になりましたextension Array : Codable where Element : Codable { ... }let elements = try container.decode([A : R].self, forKey: .elements) (edited)CGAffineTransform の逆行列は transform.inverted() なのに、 ARKit 等で使う simd の matrix_float4x4 の逆行列は matrix.inverse になってる・・・CGAffineTransform はかけ算も concatenating だし、基本的に行列として扱わないネーミングなのかな? (edited)Vector2 を Codable にして JSON に変換すると {"x":2,"y":3} のように出力させる実装をする 2. Library A の中で Vector2 を持つ struct Foo : Codable を作る 3. Library A を使う App B を作る 4. App B のあるファイルで Library A を import せず に Vector2 を Codable にして JSON に変換すると [2, 3] のように出力させる実装をする 5. App B の別のファイルで Library A を import して Vector2 を JSON に変換すると [2, 3] 、 Foo を JSON に変換するとその中の Vector2 は {"x":2,"y":3} というのができた。 (edited)Vector2 に二通りの Codable の実装をして、それぞれ呼び分けることができた。なんとなくできない気がしてたけど、問題なかった。 (edited)import で Codable の実装を切り替えたりできそうですね。Codable に限りませんが)import LibraryA をせずに Vector2 を持つ struct を Codable にしようとしたらエラーになったから、これはと思って試したんだけどimport LibraryA せずに Vector2 を持つ struct が Codable にできるようになってしまった。逆に Codable を付けようとすると redundant でエラーになる・・・。 (edited)[omochi@omochi-iMacPro k (master=)]$ cat Sources/App/main.swift import Nature import Japan import US var animals: [AnimalProtocol] = [] animals.append(createJapanCat()) animals.append(createUSCat()) animals.forEach { animal in print(animal.speak()) } [omochi@omochi-iMacPro k (master=)]$ swift run にゃあ meow&+ ならオーバーフローしても落ちないですfunc addingReportingOverflow(_ other: Int) -> (partialValue: Int, overflow: Bool)addWithOverflow の名前が変わったんですね infix operator %+ struct E : Error {} func %+(a: UInt32, b: UInt32) throws -> UInt32 { let c = a.addingReportingOverflow(b) if c.overflow { throw E() } return c.partialValue } try UInt32(0x80_00_00_00) %+ UInt32(0x80_00_00_00)Swift version 4.1 (swift-4.1-RELEASE)/usercode/main.swift:11:27: warning: result of operator '%+' is unused try UInt32(0x80_00_00_00) %+ UInt32(0x80_00_00_00) ~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~ Fatal error: Error raised at top level: main.E(): file /home/buildnode/jenkins/workspace/oss-swift-4.1-package-linux-ubuntu-16_04/swift/stdlib/public/core/ErrorType.swift, line 191 Current stack trace: 0 libswiftCore.so 0x00007f8e1fc285c0 _swift_stdlib_reportFatalErrorInFile + 221 1 libswiftCore.so 0x00007f8e1f9973dc <unavailable> + 1369052 2 libswiftCore.so 0x00007f8e1fbd1222 <unavailable> + 3703330 3 libswiftCore.so 0x00007f8e1fbd2689 <unavailable> + 3708553 4 libswiftCore.so 0x00007f8e1f996ad6 <unavailable> + 1366742 5 libswiftCore.so 0x00007f8e1fbd0feb <unavailable> + 3702763 6 libswiftCore.so 0x00007f8e1f996ad6 <unavailable> + 1366742 7 libswiftCore.so 0x00007f8e1fb03f79 <unavailable> + 2862969 8 libswiftCore.so 0x00007f8e1f9d4960 swift_errorInMain + 318 10 swift 0x0000000000fed1ce <unavailable> + 12505550 11 swift 0x0000000000ff1692 <unavailable> + 12523154 12 swift 0x00000000004d9076 <unavailable> + 888950 13 swift 0x00000000004c35d3 <unavailable> + 800211 14 swift 0x00000000004beecc <unavailable> + 782028 15 swift 0x00000000004778c4 <unavailable> + 489668 16 libc.so.6 0x00007f8e22141740 __libc_start_main + 240 17 swift 0x0000000000475179 <unavailable> + 479609 /usr/bin/swift[0x3f24d54] /usr/bin/swift[0x3f25096] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f8e23a17390] ...array[i] などと同じく API 設計上の意図的なものだと思うので。 (edited)let o1 = tanh(x ⊗ w1 + b1) 内積演算子(テンソル積演算子?)、どうやって入力するんだろう.. (edited)import TensorFlow let x = Tensor<Float>(shape: [1, 2], repeating: 0.1) let y = Tensor<Float>(shape: [3, 4], repeating: 0.1) let matmul = x ⊗ y print(matmul)
test.swift:5:16: error: internal error generating TensorFlow graph: Dimensions must be equal, but are 2 and 3 for 'op.test.swift.5.16' (op: 'MatMul') with input shapes: [1,2], [3,4]. let matmul = x ⊗ y (edited)import TensorFlow let x = Tensor<Float>(shape: [1, 2], repeating: 0.1) let y = Tensor<Float>(shape: [3, 4], repeating: 0.1) let matmul = x ⊗ y print(matmul)main.swift:4:21: error: internal error generating TensorFlow graph: GraphGen cannot lower a 'receive' from the host yet let y = Tensor<Float>(shape: [3, 4], repeating: 0.1) ^~/Library/Developer/Xcode/UserData/ に入れればすぐ出ます。 (edited)function (lhs ... ) { ... }JSONEncoder.KeyEncodingStrategy.convertToSnakeCaseとJSONDecoder.KeyDecodingStrategy.convertFromSnakeCaseが非対称となる問題のスレッドがSwift Forumではじまりました。 https://forums.swift.org/t/handling-edge-cases-in-jsonencoder-jsondecoder-key-conversion-strategies-sr-6629/12384
import Foundation struct S: Codable { var myURLProperty: String } let encoder = JSONEncoder() encoder.keyEncodingStrategy = .convertToSnakeCase let data = try encoder.encode(S(myURLProperty: "property")) let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase let decoded = try decoder.decode(S.self, from: data) // "No value associated with key CodingKeys(stringValue: \"myURLProperty\", intValue: nil) (\"myURLProperty\"), converted to my_url_property."
上記コードはLinuxでは動きません。 (edited)swiftの標準入力へソースコードを渡して実行させる時、-以降をCommandLine.argumentsとして取り出せるのね。 $ echo 'dump(CommandLine.arguments)' | swift -Onone - -verbose ▿ 2 elements - "-" - "-verbose"▿ 2 elements - "-" - "-verbose"UserDefaults.argumentDomainサポートは4.2から。 @swift-4.1.3 @swift-4.2.4 - -param1 yes import Foundation print(CommandLine.arguments) print("param1: \(UserDefaults.standard.bool(forKey: "param1"))")["-", "-param1", "yes"] param1: true["-", "-param1", "yes"] param1: falseprotocol A{} struct S<X> {} extension S: A where X == Int {} extension S: A where X == String {}protocol A{} struct S<X> {} extension S: A where X == Int {} extension S: A where X == String {}swift-4.1.1-RELEASE/usercode/main.swift:4:14: error: redundant conformance of 'S<X>' to protocol 'A' extension S: A where X == Int {} ^ /usercode/main.swift:5:1: note: 'S<X>' declares conformance to protocol 'A' here extension S: A where X == String {} ^protocol IntOrString {} extension Int : IntOrString {} extension String : IntOrString {} extension S: A where X: IntOrString {}enum AorB { case a(A) case b(B) } protocol AorBProtocol { var _value: AorB { get } } extension A: AorBProtocol { var _value: AorB { return .a(self) } extension B: AorBProtocol { var _value: AorB { return .b(self) } extension Array: Foo where Element: AorBProtocol { func fooFunc() { forEach { switch $0._value { case .a(let a): // write a case here case .b(let b): // write b case here } } } } (edited)protocol A1 {} protocol A2: A1 {} protocol A3: A2 {} struct C<R>: A1 extension C: A2, A3 where R == X extension C: A2 where R == Y (edited)Complex<R> にして、複素数体 C = Complex<Real> と ガウス整数環 Complex<Int> を共通化しようとしまして、 (edited)protocol XorY {} struct X: XorY {} struct Y: XorY {} protocol A1 {} protocol A2: A1 {} protocol A3: A2 {} struct C<R>: A1 { } extension C: A2 where R: XorY { } extension C: A3 where R == Y { }protocol XorY {} struct X: XorY {} struct Y: XorY {} protocol A1 {} protocol A2: A1 {} protocol A3: A2 {} struct C<R>: A1 { } extension C: A2 where R: XorY { } extension C: A3 where R == Y { }swift-4.1.1-RELEASEprotocol XorY {} struct X: XorY {} struct Y: XorY {} protocol A1 { func a1() -> String } protocol A2: A1 { func a2() -> String } protocol A3: A2 { func a3() -> String } struct C<R>: A1 { func a1() -> String { return "a1\(R.self)" } } extension C: A2 where R: XorY { func a2() -> String { return "a2\(R.self)" } } extension C: A3 where R == Y { func a3() -> String { return "a3\(R.self)" } } print(C<X>().a1()) print(C<X>().a2()) // print(C<X>().a3()) // compile error print(C<Y>().a1()) print(C<Y>().a2()) print(C<Y>().a3()) シンプルな例ならイケそうな雰囲気はありますが…もしかしたら別のところでダメなのかも (edited)protocol XorY {} struct X: XorY {} struct Y: XorY {} protocol A1 { func a1() -> String } protocol A2: A1 { func a2() -> String } protocol A3: A2 { func a3() -> String } struct C<R>: A1 { func a1() -> String { return "a1\(R.self)" } } extension C: A2 where R: XorY { func a2() -> String { return "a2\(R.self)" } } extension C: A3 where R == Y { func a3() -> String { return "a3\(R.self)" } } print(C<X>().a1()) print(C<X>().a2()) // print(C<X>().a3()) // compile error print(C<Y>().a1()) print(C<Y>().a2()) print(C<Y>().a3())swift-4.1.1-RELEASEa1X a2X a1Y a2Y a3Ypublic typealias 𝐑 = RealNumberenum AorB { case a(A) case b(B) } protocol AorBProtocol { var _value: AorB { get } } すいません、こちらはちょっと理解が不十分でした、public protocol ComplexType: Ring { associatedtype Base: Ring init(_ x: Base) init(_ x: Base, _ y: Base) static var imaginaryUnit: Self { get } var realPart: Base { get } var imaginaryPart: Base { get } var inverse: Self? { get } var conjugate: Self { get } } ってして、 protocol extension つける方向で行こうかと思いますextension Array: Equatable where Element==Int {} (edited)extension Array: Equatable where Element==Int {}swift-4.1.1-RELEASE/usercode/main.swift:1:18: warning: conformance of 'Array<Element>' to protocol 'Equatable' was already stated in the type's module 'Swift' extension Array: Equatable where Element==Int {} ^ Swift.Array<Element>:1:11: note: 'Array<Element>' declares conformance to protocol 'Equatable' here extension Array : Equatable where Element : Equatable { ^extension Array: Equatable where Element==Never { static func == (lhs: Array, rhs: Array) -> Bool { return true } } (edited)extension Array: Equatable where Element==Never { static func == (lhs: Array, rhs: Array) -> Bool { return true } }extension Array: Equatable where Element==Never { static func == (lhs: Array, rhs: Array) -> Bool { return true } }swift-4.1.1-RELEASE/usercode/main.swift:1:18: warning: conformance of 'Array<Element>' to protocol 'Equatable' was already stated in the type's module 'Swift' extension Array: Equatable where Element==Never { static func == (lhs: Array, rhs: Array) -> Bool { return true } } ^ /usercode/main.swift:1:63: note: operator function '==' will not be used to satisfy the conformance to 'Equatable' extension Array: Equatable where Element==Never { static func == (lhs: Array, rhs: Array) -> Bool { return true } } ^ Swift.Array<Element>:1:11: note: 'Array<Element>' declares conformance to protocol 'Equatable' here extension Array : Equatable where Element : Equatable { ^#if swift(>=4.2) print("swift-4.2") #elseif swift(>=4.1.50) print("swift-4.1.50") #elseif swift(>=4.1.2) print("swift-4.1.2") #endifswift-4.1.50Swift version 4.2-dev (LLVM a38ff55b31, Clang 5272858825, Swift defc3e9073) Target: x86_64-unknown-linux-gnu (edited)nil パターンのテスト書かなくて済むメリットがあるのかなという意味です¬AutoLayout は多分そもそもGitHubでリポジトリ作れないしCartfileとかで指定できなさそうな気が let f = Float.nan let a = [f] let b = [f] print(f == f) // false print(a == a) // true print(a == b) // falselet f = Float.nan let a = [f] let b = [f] print(f == f) // false print(a == a) // true print(a == b) // falseswift-4.1.1-RELEASEfalse true falseprint(Float.nan == Float.nan) (edited)let f = Float.nan let a = Optional(f) let b = Optional(f) print(f == f) // false print(a == a) // false print(a == b) // falselet f = Float.nan let a = Optional(f) let b = Optional(f) print(f == f) // false print(a == a) // false print(a == b) // falseswift-4.1.1-RELEASEfalse false falseDictionary や Set もおかしくなるんじゃない?Optional は中身が一つしかないからそれの == を使うだろうけど、 Dictionary や Set だと Array と同じショートカットが行われてそう。Array のバグなのか、 Float の(というか IEEE の)問題なのか。a == a であるとして設計されてそうだしEquatable なのに equality じゃなくて equivalence なのか・・・。英語むずい・・・。Float の == を変えるのも難しいよね・・・。Array 等のショートカットをやめる 3. Float 等の == を変える だけど。結局 1 にしかならなさそう。var d: [Float: String] = [:] d[.nan] = "a" d[.nan] = "b" d[.nan] = "c" print(d.count) print(d[.nan]) print(d == d)var d: [Float: String] = [:] d[.nan] = "a" d[.nan] = "b" d[.nan] = "c" print(d.count) print(d[.nan]) print(d == d)swift-4.1.1-RELEASE3 nil true/usercode/main.swift:6:7: warning: expression implicitly coerced from 'String?' to Any print(d[.nan]) ^~~~~~~ /usercode/main.swift:6:8: note: provide a default value to avoid this warning print(d[.nan]) ~^~~~~~ ?? <#default value#> /usercode/main.swift:6:8: note: force-unwrap the value to avoid this warning print(d[.nan]) ~^~~~~~ ! /usercode/main.swift:6:8: note: explicitly cast to Any with 'as Any' to silence this warning print(d[.nan]) ~^~~~~~ as Any&== を IEEE 754 に従った素の計算にして、 == だと反射率を満たすようにすればいい気が。&== 入れるなら == がIEEEに従う じゃないですか?== は Equatable で規定されるものだから、 Equatable の == が反射率を満たす必要があることを明記して&== は &+ 等と同様の余分なオーバーヘッドのない計算をしてくれる演算子でいいのでは?true でいいんじゃないかなぁ== .nan を見て、このコードバグってんぞ→バグってなかった!ってなりそうInt の + だってそうでしょ?Float や Double の == より Int の + を使う機会の方がずっと多いのでは?+ や * は使っても == はそんなに使わなさそう。Float や Double で、 CPU 上で計算してる時点でパフォーマンスにこだわるケースじゃなさそう。Equatable はあくまで計算結果の値についてなので、成り立つように思います。Equatable はあくまで値についての性質なので、どのような式で nan が導かれても推移律は満たされることになるかと。a == aのケースについて話されてるかはこれから読みます。Array.== first looks to referential equality of underlying buffer...Array.== first looks to referential equality of underlying Element.==. As a consequence, an array of NaN compares equal to another array of NaN if they share the same buffer, but otherwise false. This is an undesirable outcome. 頭から書いてあったThe last time that this topic was brought up, competing demands voiced by different people were not possible to reconcile: 1) Equatable `==` must be a full equivalence relation. 2) Floating-point types must conform to `Equatable` and not to some alternative such as `PartiallyEquatable`. 3) Floating-point `==` must be IEEE-compliant (at least in the concrete context), and therefore *not* a full equivalence relation. 4) IEEE-compliant floating-point equivalence must be spelled `==` and not some alternative such as `&==`. 5) Behavior of `==` must not change between generic and concrete contexts.protocol A { static func hoge() } struct B: A { static func hoge() { print("B") } } extension Optional: A where Wrapped: A { static func hoge() { print("Optional") } } struct F<T> { static func fuga() { switch T.self { case is A.Type: (T.self as! A.Type).hoge() default: fatalError() } } } F<B>.fuga() // B // warning: Swift runtime does not yet support dynamically querying conditional conformance F<B?>.fuga() // fatalError (edited)swift-4.2-DEVELOPMENT-SNAPSHOT-2018-04-23-aHList を HCons と HNil に限定できないのが辛いですね。 enum でも書けなさそうだし・・・。List なら↓みたいに書けるんですけどね〜。 enum List<Element> { case `nil` indirect case cons(Element, List<Element>) } let a: List<Int> = .cons(2, .cons(3, .cons(5, .nil))) (edited)enumが型パラメータを取れないと無理なんですよね……。canImportはimportの様にシンボルを使う事は出来ないのか…。 @swift-main
import Foundation let killSignals: [Int32] = { var signals = [SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGQUIT] #if canImport(Glibc.SIGSYS) signals.append(Glibc.SIGSYS) #endif return signals }() (edited)<stdin>:4:5: error: unexpected platform condition argument: expected identifier #if canImport(Glibc.SIGSYS) ^ (edited)public struct Uniform { var base: RandomNumberGenerator init(base: RandomNumberGenerator) { self.base = base } /// Returns a value from uniform [low, high) distribution. public mutating func next(low: Float, high: Float) -> Float { let uint32: UInt32 = base.next() return (high - low) * (Float(bitPattern: uint32 >> 9 | 0x3f80_0000) - 1) + low } } extension RandomNumberGenerator { public var uniform: Uniform { return Uniform(base: self) } } こういうの作ろうと思ったんですがRNGがstructだと内部状態コピーされるから微妙ですね…… (edited)next(range: Range<Float>) を RandomNumberGenerator に生やすとか?extension で追加してもいい気も (edited)next(range: Range<Float>)とnext(mu: Float, sigma: Float)だと分かりづらくないですかね?Random は struct だけどそれは起こらないのと、struct の場合var a = FooRandom() var b = a a.next() == b.next() // true になるんだから、 Uniform もそれでいいんじゃないかな?var a = FooRandom() print(a.uniform.next(...) print(a.uniform.next(...) これで同じのが出るのが嫌か。uniform を get set なプロパティにしてBool の toggle とかと同じように元の struct に変更を反映できない?set で base を self に代入すればいいのか。 (edited)swift public struct Uniform { var base: RandomNumberGenerator init(base: RandomNumberGenerator) { self.base = base } /// Returns a value from uniform [low, high) distribution. public mutating func next(low: Float, high: Float) -> Float { print("base before; \(base)") let uint32: UInt32 = base.next() print("base after; \(base)") return (high - low) * (Float(bitPattern: uint32 >> 9 | 0x3f80_0000) - 1) + low } } extension RandomNumberGenerator { public var uniform: Uniform { get { return Uniform(base: self) } set { print("before set: \(self)") self = uniform.base as! Self print("set self: \(self) \(uniform.base)") } } } struct DummyRNG: RandomNumberGenerator { static var `default` = DummyRNG.init() var state: UInt32 = 0 mutating func next<T>() -> T where T : FixedWidthInteger, T : UnsignedInteger { state += 123456789 return T(state) } } print(DummyRNG.default.uniform.next(low: 0, high: 1)) print(DummyRNG.default.uniform.next(low: 0, high: 1)) print(DummyRNG.default.uniform.next(low: 0, high: 1))base before; DummyRNG(state: 0) base after; DummyRNG(state: 123456789) before set: DummyRNG(state: 0) set self: DummyRNG(state: 0) DummyRNG(state: 0) 0.02874446 base before; DummyRNG(state: 0) base after; DummyRNG(state: 123456789) before set: DummyRNG(state: 0) set self: DummyRNG(state: 0) DummyRNG(state: 0) 0.02874446 base before; DummyRNG(state: 0) base after; DummyRNG(state: 123456789) before set: DummyRNG(state: 0) set self: DummyRNG(state: 0) DummyRNG(state: 0) 0.02874446Uniform<Random : RandomNumberGenerator> にした方が Swifty じゃないですか?base を fileprivate にする PR 送ろうかと思ったら、逆に 1.0.0 から 1.0.1 で internal → public な変更がされてるんですが、この意図は何でしょう?1.0.0 → 1.1.0 の変更だと思います。-alpha や -beta, -beta.2 等を付けておくのがオススメです。1.0.0 から始めずに 0.1.0 から始めた方が気軽に破壊的変更しやすいです。)base を外部から使ってなくないですか? https://github.com/t-ae/xorswift/blob/swift4.2/Sources/Uniform.swiftbase.xとかが出てきます.base で検索してたFloat.random(in:)がありましたね。 normalもこっちの形式に揃えるほうがいいんだろうか……strings.compactMap(Int.init) で、 flatMap 以前なので 3 週古くて(リネーム前の flatMap → Array を返す flatmap → reduce)reduce 使うにしても今だったら reduce(into:_:) だし。let a = [[2], [3 ,5]] for var (i, numbers) in a.enumerated() { numbers.append(3) print("\(i): \(numbers)") }let a = [[2], [3 ,5]] for var (i, numbers) in a.enumerated() { numbers.append(3) print("\(i): \(numbers)") }swift-4.1.1-RELEASE0: [2, 3] 1: [3, 5, 3]/usercode/main.swift:3:10: warning: variable 'i' was never mutated; consider changing to 'let' constant for var (i, numbers) in a.enumerated() { ^numbers は var に、 i は let にしたい。let a = [[2], [3 ,5]] for (i, var numbers) in a.enumerated() { numbers.append(3) print("\(i): \(numbers)") }let a = [[2], [3 ,5]] for (i, var numbers) in a.enumerated() { numbers.append(3) print("\(i): \(numbers)") }swift-4.1.1-RELEASE0: [2, 3] 1: [3, 5, 3]var と let に bind したい。 @swiftbot
let a = [[2], [3 ,5]] var iterator = a.enumerated().makeIterator() if var (i, numbers) = iterator.next() { numbers.append(0) print("\(i): \(numbers)") }let a = [[2], [3 ,5]] var iterator = a.enumerated().makeIterator() if var (i, numbers) = iterator.next() { numbers.append(0) print("\(i): \(numbers)") }swift-4.1.1-RELEASE0: [2, 0]/usercode/main.swift:4:9: warning: variable 'i' was never mutated; consider changing to 'let' constant if var (i, numbers) = iterator.next() { ^if case (let i, var numbers)? = iterator.next() {case にしちゃえばいいのか。ありがとうございます!_random()をrandom(in: UnboundedRange)にしたら?って提案しようかと思うんですがこういう細かい&そもそもまだ固まってない内容もフォーラムにスレッド立てていいんですかね? RandomUnificationのスレはちょっと古くて……random(in: UnboundedRange) は新しい API の提案だし、 reduce(into:_:) や toggle 、 compactMapValues を考えると、単独の API の提案は全然ありな気がします。FixedWidthInteger に限らず検討することになるかもしれないにしても、 pitch は気軽に投げていいんじゃないでしょうか。struct Foo { var bar: Bar { mutating get { ... } } } ↓に書き換えた方がいいでしょうか? struct Foo { mutating func bar() -> Bar { ... } }get されてから lazy に読み込んでキャッシュしたいケースです。var foo1 = Foo() var foo2 = foo1 var bar = foo2.bar というときに、foo1 にキャッシュが共有されないというのが許容出来る場合、僕なら mutating func bar() にします。class にするか、グローバルにキャッシュを持つしかない。protocol P { associatedtype T func f(_ g: @escaping (T) -> Void) } class C<S>: P { typealias T = S private let _f: ((S) -> Void) -> Void init<Q: P>(q: Q) where Q.T == T { // Error: cannot assign value of type '((S) -> Void) -> Void' to type '((S) -> Void) -> Void' self._f = { g -> Void in q.f(g) } } func f(_ g: @escaping (S) -> Void) { self._f(g) } }protocol P { associatedtype T func f(_ g: @escaping (T) -> Void) } class C<S>: P { typealias T = S private let _f: (@escaping (S) -> Void) -> Void init<Q: P>(q: Q) where Q.T == T { // Error: cannot assign value of type '((S) -> Void) -> Void' to type '((S) -> Void) -> Void' self._f = { g -> Void in q.f(g) } } func f(_ g: @escaping (S) -> Void) { self._f(g) } }cannot assign value of typeのエラーわかりにくい問題、最新のXcodeだと治ってて一発でわかりますよ@escaping入れなきゃいけない位置を秒で特定できたのはちょい謎@escaping必要だって、、わいのXcodeは表示したんや…そのはずや…self の再宣言で LLDB 壊れますね class Example { func ok() { let f = { [weak self] in guard let strongSelf = self else { return } // Set a breakpoint at here print(strongSelf) } f() } func error() { let f = { [weak self] in guard let `self` = self else { return } // Set a breakpoint at here print(self) } f() } } Example().ok() Example().error()(lldb) br set --file example.swift --line 7 Breakpoint 1: where = example`closure #1 () -> () in example.Example.ok() -> () + 111 at example.swift:7, address = 0x00000001000017df (lldb) br set --file example.swift --line 18 Breakpoint 2: where = example`closure #1 () -> () in example.Example.error() -> () + 111 at example.swift:18, address = 0x00000001000019cf (lldb) r Process 6298 launched: '/Users/yuki.kokubun/Development/self-self-lldb/example' (x86_64) Process 6298 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x00000001000017df example`closure #1 in Example.ok(self=0x0000000100802b30) at example.swift:7 4 guard let strongSelf = self else { return } 5 6 // Set a breakpoint at here -> 7 print(strongSelf) 8 } 9 10 f() Target 0: (example) stopped. (lldb) po self ▿ Optional<Example> - some : <Example: 0x100802b30> (lldb) c Process 6298 resuming example.Example Process 6298 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1 frame #0: 0x00000001000019cf example`closure #1 in Example.error(self=0x0000000100a01030) at example.swift:18 15 guard let `self` = self else { return } 16 17 // Set a breakpoint at here -> 18 print(self) 19 } 20 21 f() Target 0: (example) stopped. (lldb) po self error: warning: <EXPR>:12:9: warning: initialization of variable '$__lldb_error_result' was never used; consider replacing with assignment to '_' or removing it var $__lldb_error_result = __lldb_tmp_error ~~~~^~~~~~~~~~~~~~~~~~~~ _ error: <EXPR>:18:5: error: value of type 'Example' has no member '$__lldb_wrapped_expr_2' $__lldb_injected_self.$__lldb_wrapped_expr_2( ^~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~fr var は下のようになるので単純な名前ベースでの解決をしようとすると死ぬのが原因…? (lldb) fr var (@lvalue example.Example?) self = 0x0000000100a01030 (example.Example) self = 0x0000000100a01030 {}self?. で書くか、 クロージャの中で必要な変数をそれぞれguardでアンラップする、って感じに最近はしてますね。guard let `self` = self else { return } ^ のところをselfじゃなくて、selfの先を3〜4つアンラップする感じd。guard let self = self else { return } <= これは見た目美しいけどトラブルが多いので良くない、 strongSelf <= これは人によって色々だしどう書いても美しくない、Error のインスタンスが手元にあるときに、それでクラッシュさせる ( try! に失敗したのと同じ状態にする)簡単な方法ってありますっけ? fatalError("\(error)") でもいいのかもしれませんが、 Error から String に情報が落ちてしまってますし。try! throw errortry ! { throw error }() だと Never でないので guard で使えないですし。try! throw error は throw が関数じゃないからできなくない?internal func fatalError<E: Error>(with error: E) -> Never { try! { throw error }() fatalError("Never reaches here.") } という微妙なユーティリティ関数を作ろうとしたけどもっといい方法はないかなと。throw new RuntimeException(exception); とかでいいんだけど。fatalError じゃなくて preconditionFailure がいいかな。 precondition なのか微妙だけど。)String(reflecting: error) で同等みたいです。_unexpectedError の返り値の型は Never ではないのですねCMSampleBufferGetImageBuffer(_:) みたいな関数群があるけど https://developer.apple.com/documentation/coremedia/1489236-cmsamplebuffergetimagebufferDispatchQueue.global(qos: .default).async { // この中で [NSException raise] が呼ばれていて、 // breakpoint set -S raise で止まった状態を想定してください。 // ここで、この doSomething を呼び出す task を誰が追加したのか // 追跡したい感じです。 doSomething() }(lldb) th backtrace * thread #3, queue = 'com.apple.root.default-qos', stop reason = breakpoint 1.1 frame #0: 0x000000010e89e001 libobjc.A.dylib`objc_exception_throw frame #1: 0x000000010f2090b9 CoreFoundation`-[NSException raise] + 9 * frame #2: 0x000000010df90ea6 StackChain`doInnerSomething() at ViewController.swift:8 frame #3: 0x000000010df90e19 StackChain`doSomething() at ViewController.swift:4 frame #4: 0x000000010df910c9 StackChain`closure #1 in ViewController.onButton() at ViewController.swift:14 frame #5: 0x000000010df910fd StackChain`thunk for @escaping @callee_guaranteed () -> () at ViewController.swift:0 frame #6: 0x000000011359b7ab libdispatch.dylib`_dispatch_call_block_and_release + 12 frame #7: 0x000000011359c7ec libdispatch.dylib`_dispatch_client_callout + 8 frame #8: 0x00000001135a1619 libdispatch.dylib`_dispatch_queue_override_invoke + 1451 frame #9: 0x00000001135a836c libdispatch.dylib`_dispatch_root_queue_drain + 664 frame #10: 0x00000001135a8076 libdispatch.dylib`_dispatch_worker_thread3 + 132 frame #11: 0x0000000113ac7169 libsystem_pthread.dylib`_pthread_wqthread + 1387 frame #12: 0x0000000113ac6be9 libsystem_pthread.dylib`start_wqthread + 13 (lldb) thread backtrace -e trueでEnqueued from…の内容も見られますね。(lldb) h th b Show thread call stacks. Defaults to the current thread, thread indexes can be specified as arguments. Use the thread-index "all" to see all threads. Use the thread-index "unique" to see threads grouped by unique call stacks. Syntax: Command Options Usage: thread backtrace [-c <count>] [-s <frame-index>] [-e <boolean>] -c <count> ( --count <count> ) How many frames to display (-1 for all) -e <boolean> ( --extended <boolean> ) Show the extended backtrace, if available -s <frame-index> ( --start <frame-index> ) Frame in which to start the backtrace/usr/lib/system/introspectionを使った機能みたいです。$ ls /usr/lib/system/introspection libdispatch.dylib* libsystem_pthread.dylib* * @discussion * These hooks are only available in the introspection version of the library, * loaded by running a process with the environment variable * DYLD_LIBRARY_PATH=/usr/lib/system/introspectionlldbを直接起動する場合とかは自分で設定する必要があるみたいです。target module list かけてみて libdispatch.dylib が本物っぽいかどうかだけ確認してみますprocess launch -v DYLD_LIBRARY_PATH=/usr/lib/system/introspectionで/usr/lib/system/introspection/libdispatch.dylibをロードしただけでは、thread backtrace -e trueは意図した通りに動きませんでした。 /Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylibってのをlldb-rpc-serverは使ってるけど、lldbで plugin load /Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib してもダメだった。 (edited)process launch -v DYLD_LIBRARY_PATH=/usr/lib/system/introspection -v DYLD_INSERT_LIBRARIES=/Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib でイケた。thread backtrace -e true in lldbswift -frontend -replなんてのがあったのね。 $ swift -frontend -repl *** You are running Swift's integrated REPL, *** *** intended for compiler and stdlib *** *** development and testing purposes only. *** *** The full REPL is built as part of LLDB. *** *** Type ':help' for assistance. *** (swift) :help Available commands: :quit - quit the interpreter (you can also use :exit or Control+D or exit(0)) :autoindent (on|off) - turn on/off automatic indentation of bracketed lines :constraints debug (on|off) - turn on/off the debug output for the constraint-based type checker :dump_ir - dump the LLVM IR generated by the REPL :dump_ast - dump the AST representation of the REPL input :dump_decl <name> - dump the AST representation of the named declarations :dump_source - dump the user input (ignoring lines with errors) :print_decl <name> - print the AST representation of the named declarations :print_module <name> - print the decls in the given module, but not submodules API documentation etc. will be here eventually. (swift) $ swift のときに突入するのがそれだと思ってました (edited)lldbを使わないので、--privileged無しのdockerでも使える。--privileged無しdockerなので、Herokuで動いてるSwiftボットでも、修正すれば使える様になりそう。swift -deprecated-integrated-repl がそれですね。[omochi@omochi-iMac-PC43 bne-loci (master *+=)]$ swift -deprecated-integrated-repl *** You are running Swift's integrated REPL, *** *** intended for compiler and stdlib *** *** development and testing purposes only. *** *** The full REPL is built as part of LLDB. *** *** Type ':help' for assistance. *** (swift) ^D [omochi@omochi-iMac-PC43 bne-loci (master *+=)]$ swift Welcome to Apple Swift version 4.2 (swiftlang-1000.0.36 clang-1000.0.4). Type :help for assistance. 1> ^D [omochi@omochi-iMac-PC43 bne-loci (master *+=)]$ swift -frontend -repl *** You are running Swift's integrated REPL, *** *** intended for compiler and stdlib *** *** development and testing purposes only. *** *** The full REPL is built as part of LLDB. *** *** Type ':help' for assistance. *** (swift) ^D-frontend -repl のほうが -deprecated-integrated-repl か・・・print_declとprint_moduleくらいだけど、どれも出力が大きくなるからボットで使えてもありがたみが薄いかな?:print_decl Equatableprotocol Equatable { static func == (lhs: Self, rhs: Self) -> Bool } extension Equatable { @inlinable static func != (lhs: Self, rhs: Self) -> Bool }-frontend -replサポート出来た。swift-DEVELOPMENT-SNAPSHOT-2018-08-26-a があるけど https://github.com/apple/swift/tags にタグが無いな。gitで見ても無さげ。T: Hoge みたいに書けるけど、handle 書くの、気持ち悪い気がしたけど defer 的な気持ちで見れば良いのか。do/catch で囲まなくてよいのでネストが深くならないのが良い?finally を採用せずに defer にしたんだったら、この handle みたいなのの方が理に適ってる気がするけどどうだろう? (edited)handle とスコープについては、 Go の defer はスコープ関係なく関数単位だったはずだから、 handle はどうなんだろう?とさっきから思ってる。StringからNSStringへの暗黙変換が起きる条件って何だろう?NSString.character(at:)は、Linuxでは4.2から起きる。 @swift-4.0.3 @swift-4.1.3 @swift-4.2.4 -frontend -repl import Foundation "test".character(at: 0) (edited)<REPL Input>:1:1: error: value of type 'String' has no member 'character' "test".character(at: 0) ^~~~~~ ~~~~~~~~~ Swift.String:42:16: note: did you mean 'characters'? public var characters: String.CharacterView { get set } ^ (edited)<REPL Input>:1:1: error: value of type 'String' has no member 'character' "test".character(at: 0) ^~~~~~ ~~~~~~~~~ Swift.String:10:16: note: did you mean 'characters'? public var characters: String.CharacterView { get set } ^ Swift.String:8:16: note: did you mean '_characters'? public var _characters: String._CharacterView { get set } ^ (edited)$ echo 'import Foundation; "test".character(at: 0)'|swift -frontend -repl -sdk `xcrun --sdk macosx --show-sdk-path` <REPL Input>:1:20: error: value of type 'String' has no member 'character' import Foundation; "test".character(at: 0) ^~~~~~ ~~~~~~~~~ Swift.String:10:16: note: did you mean 'characters'? public var characters: String.CharacterView { get set } ^ Swift.String:8:16: note: did you mean '_characters'? public var _characters: String._CharacterView { get set } ^Swift.String であり、2) Swift.String が _ObjectiveCBridgeable であり、 3) lookupするメンバー名が Swift.String に生えておらず、 4) ブリッジ先タイプにはそのメンバーが存在し 5) 存在するモジュールが Clang モジュールの Foundation 以外のとき。 っていう条件なので、 corelibs-foundation は 5 の条件をすり抜けて見えちゃっている感じっぽいですね。 (edited)NSStringにインスタンスメンバーを追加すると、Stringからも使えてしまうと。 @swift-4.0.3 @swift-4.1.3 @swift-4.2.4 -frontend -repl import Foundation extension NSString { func hoge() -> String { return "hoge" } } "test".hoge()// r0 : String = "hoge"<REPL Input>:1:1: error: value of type 'String' has no member 'hoge' "test".hoge() ^~~~~~ ~~~~<REPL Input>:1:1: error: value of type 'String' has no member 'hoge' "test".hoge() ^~~~~~ ~~~~.swiftmodule ファイルとしてキャッシュされないですか?.swiftmodule は依存の解決には使われていなかったと思うのですが、記憶違いかも。 (edited).swiftmodule は出力されるものではありますが、他ファイルのコンパイル時に参照されて使われる物ではないですね。A.swift,B.swift, C.swiftあったときにクリーンビルドだと swift -frontend -c -primary-file A.swift B.swift C.swift swift -frontend -c A.swift -primary-file B.swift C.swift swift -frontend -c A.swift B.swift -primary-file C.swift の 3 フロントエンド実行されて、frontend に -primary-file じゃないファイルの .swiftmodule があったらそれに読み替えるみたいな機能はないので。${PROJECT_TEMP_ROOT}/XCBuildData/*-manifest.xcbuild に生成します。 それらをSwiftPMの.build/debug.yamlとかと比較すると違いを調べやすいかも? (edited)$ cat A.swift @available(*, introduced: 1) public func funcA() { print("funcA") } $ cat B.swift public func funcB() { print("funcB") funcA() } $ cat C.swift public func funcC() { print("funcC") } $ cat output.json { "A.swift": { "object": "Derived/A.o", "swiftmodule": "Derived/A~partial.swiftmodule", "swift-dependencies": "Derived/A.swiftdeps", }, "B.swift": { "object": "Derived/B.o", "swiftmodule": "Derived/B~partial.swiftmodule", "swift-dependencies": "Derived/B.swiftdeps", }, "C.swift": { "object": "Derived/C.o", "swiftmodule": "Derived/C~partial.swiftmodule", "swift-dependencies": "Derived/C.swiftdeps", }, "": { "swift-dependencies": "Derived/buildrecord.swiftdeps" } } $ mkdir -p Derived な状態から、 $ xcrun swiftc -v -incremental -output-file-map output.json A.swift B.swift C.swift -module-name MyModule -emit-library -emit-module -o Derived/MyModule.dylib でとりあえずクリーンビルドして、Derived ディレクトリの中身見たり、A.swiftの@available消して同コマンド実行して何が起こってるか確認したりすると面白いです。 (edited)swiftc コマンドに -enable-batch-mode 追加してあげるとXcode10の挙動と同等に。 (edited)[swift 4.2] みたいなバッジがついてたりしたら、安心です
あと、プロジェクトの中で、あるモジュールは4.1、あるモジュールは4.2でビルドしてからリンクします、 みたいなやつ、動くのかもしれないけど信用ならないから心配。 むむ、これって何かトラブルの事例ってあるのですか?SWIFT_VERSION = 4.2になっててもswiftcへは-swift-version 4って渡すのかな?project.pbxprojでSWIFT_VERSION = 4.2になってても過去のXcodeでビルド出来るなら、SWIFT_VERSION = 4.2にしてしまっても良い様な気がしてきた。project.pbxprojでSWIFT_VERSION = 4.2になってても、Xcode 9.0.1, 9.1, 9.2, 9.3.1, 9.4.1はswiftcへ-swift-version 4を渡すのを確認した。SWIFT_VERSION = 4.2にしてもbreaking changeにならないとしても、podspecのswift_versionはどうなんだろう?(indirect.storage -> some -> value)Found 2 object leaking children[0].viewModel: SomeViewModel children[0].textField: UITextFieldSummary: Found 2 leak objects Leaked objects: 0: Description: Node Type: Any Location: .linkedNodes[0] 1: Description: Node Type: Any Location: (root) Circular reference paths: 0: .linkedNodes[0].linkedNodes[0]Sequence ( Collection ?)を型パラメータにとるのがおもしろいですね。 https://github.com/pointfreeco/swift-nonempty (edited)Collection っぽいですね。 https://github.com/pointfreeco/swift-nonempty/blob/master/Sources/NonEmpty/NonEmpty.swift#L1Image<Element>: Sequence を作ってますが Image to Image の map ができてるので。 Sequence 由来のと曖昧になりそうな気がするんですが、 Image to Image の方が優先されてますね。Sequence に map とかついてるのほんと微妙ですよねぇ。 makeIterator だけの純粋な Sequence と map とかを分離してほしい・・・。Collection として扱われるので Collection の map が呼ばれるんじゃないですか?↓とかですよね? public func map<T>(_ transform: (Element) throws -> T) rethrows -> NonEmpty<[T]> { return try NonEmpty<[T]>(transform(self.head), self.tail.map(transform)) }
[Element] を [T] に変換するんで Self じゃなくて、 higher-kinded type がないとできないんですよねぇ・・・。
NonEmpty<Element, NonEmpty<Element, C>>NonEmpty<Element, NonEmpty<Element, C>> は考えてませんでしたが(それぞれの struct を実装するイメージしてました)、多分うまくいきそうな気がします。その場合だけ init(Element, Element, C) を extension で生やせると便利そうですね〜。typealias ArrayLongerThan2<Element> = PrefixedArray<Element, PrefixedArray<Element, PrefixedArrayEnd<Element>>> となっていて、これで flatMap とかの実装が衝突して死んだみたいなエラーに出くわして、ウワァ、ダメなのかみたいに引き返したんです (edited)protocol NonEmptySequence: Sequence { var first: Element { get } } struct NonEmptyArray<Element>: NonEmptySequence { private var array: [Element] init(_ array: [Element]) { precondition(!array.isEmpty) self.array = array } var first: Element { return array[0] } func makeIterator() -> Array<Element>.Iterator { return array.makeIterator() } } (edited)protocol NonEmptySequence: Sequence { var first: Element { get } } struct NonEmptyArray<Element>: NonEmptySequence { private var array: [Element] init(_ array: [Element]) { precondition(!array.isEmpty) self.array = array } var first: Element { return array[0] } func makeIterator() -> Array<Element>.Iterator { return array.makeIterator() } } (edited)protocol NonEmptySequence: Sequence { var first: Element { get } } struct NonEmptyArray<Element>: NonEmptySequence { private var array: [Element] init(_ array: [Element]) { precondition(!array.isEmpty) self.array = array } var first: Element { return array[0] } func makeIterator() -> Array<Element>.Iterator { return array.makeIterator() } }first は Sequence じゃなくて Collection なのか。extension でも生えてないんですね。 map とかは生えてるのに・・・。protocol I { init() } protocol P { associatedtype A: I } extension P { var bar: A? { return nil } } protocol Q: P {} extension Q { var bar: A { return A() } } struct S<T: I>: Q { typealias A = T let value: T var bar: T { return value } } extension Int: I { init() { self = 0 } } let s = S(value: 42) print(s.bar) (edited)safeFirst って何ができなかったんですか? Optional を非 Optional で満たすことができなかったとかではなく??protocol P { associatedtype A var a: A? { get } } struct S<T>: P { typealias A = T let value: T var a: T { return value } } let s = S(value: 42) print(s.a)<stdin>:7:8: error: type 'S<T>' does not conform to protocol 'P' struct S<T>: P { ^ <stdin>:10:9: note: candidate has non-matching type 'T' var a: T { return value } ^ <stdin>:4:9: note: protocol requires property 'a' with type 'S<T>.A?'; do you want to add a stub? var a: A? { get } ^1. オブジェクトを全部スキャンする 2. 検査したい関数を実行する 3. スキャンしてあるweak参照の先に生きてるオブジェクトが無いことを確認する (edited)let target = createSomething() let memoryLeaks = detectLeaks(target) XCTAssertTrue( memoryLeaks.leakedObjects.isEmpty, memoryLeaks.prettyDescription )class Cat { var parent: Cat? } func createSomething() -> Cat { let cat1 = Cat() let cat2 = Cat() let cat3 = Cat() cat2.parent = cat3 cat3.parent = cat2 return cat1 }Summary: Found 0 leaked objects Leaked objects: (empty)class Cat { var parent: Cat? var child: Cat? } func createSomething() -> Cat { let cat1 = Cat() let cat2 = Cat() let cat3 = Cat() cat2.parent = cat3 cat3.parent = cat2 cat2.child = cat1 return cat1 }let json = """ [{ "id": 0, "mode": "high" },{ "id": 1, "mode": "middle" },{ "id": 2, "mode": "moddle" },{ "id": 3, "mode": "low" }] """ enum Mode: String, Decodable { case high case middle case low } struct Object: Decodable { let id: Int let mode: Mode } let objects = try! JSONDecoder().decode([Object].self, from: json.data(using: .utf8)!) print(objects) ↑のような時に、Jsonのデコードを失敗とせずid:0,1,3のObjectの配列を返すような実装がしたい場合Arrayのラッパーみたいなものを書く感じになるのでしょうか?enum Mode: String, Decodable { case high case middle case low } struct Object: Decodable { let id: Int let mode: Mode? } do { let decoder = JSONDecoder() let data = json.data(using: .utf8)! let objects = try decoder.decode([Object].self, from: data).compactMap({ $0.mode != nil }) print(objects) } catch { print(error) }import Foundation let json = """ [{ "id": 0, "mode": "high" },{ "id": 1, "mode": "middle" },{ "id": 2, "mode": "moddle" },{ "id": 3, "mode": "low" }] """ enum Mode: String, Decodable { case high case middle case low } struct Object: Decodable { let id: Int let mode: Mode? enum CodingKeys: CodingKey { case id, mode } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.id = try container.decode(Int.self, forKey: .id) self.mode = try? container.decode(Mode.self, forKey: .mode) } } let objects = try! JSONDecoder().decode([Object].self, from: json.data(using: .utf8)!).filter { $0.mode != nil } print(objects)[main.Object(id: 0, mode: Optional(main.Mode.high)), main.Object(id: 1, mode: Optional(main.Mode.middle)), main.Object(id: 3, mode: Optional(main.Mode.low))]import Foundation let json = """ [{ "id": 0, "mode": "high" }, { "id": 1, "mode": "middle" }, { "id": 2, "mode": "moddle" }, { "id": 3, "mode": "low" } ] """ enum Mode: String, Decodable { case high case middle case low } struct Object: Decodable { let id: Int let mode: Mode init(id: Int, mode: Mode) { self.id = id self.mode = mode } } struct FailableBox<T> : Decodable where T : Decodable { init(from decoder: Decoder) throws { self.value = try? T.init(from: decoder) } var value: T? } let objects: [Object] = try! JSONDecoder() .decode([FailableBox<Object>].self, from: json.data(using: .utf8)!) .compactMap { $0.value } print(objects)[main.Object(id: 0, mode: main.Mode.high), main.Object(id: 1, mode: main.Mode.middle), main.Object(id: 3, mode: main.Mode.low)]import Foundation enum Result { case win case lose case none } var results: [Int : Result] = [:] results[0] = .win results[1] = .lose results[2] = .none if results[2] == nil { print("result.2 is nil") }result.2 is nilimport Foundation enum Result { case win case lose case none } var results: [Int : Result] = [:] results[0] = .win results[1] = .lose results[2] = .some(.none) if results[2] == nil { print("result.2 is nil") }Dictionary の subscript が -> Value? だからかぁ。get と set で、 get は Optional だけど set は Optional でなくしたいケース、ときどきある気がしてる。enum Result { case win case lose case none } func foo(_ resultOrNil: Result?) { print(resultOrNil as Any) } foo(.win) foo(.lose) foo(.none) foo(Result.none)Optional(main.Result.win) Optional(main.Result.lose) nil Optional(main.Result.none)none は避けるようにした方が無難そうですね。 (edited)removeValue(forKey:) だけにして、 subscript set を非 Optional にしてほしいです・・・。set で非 Optional 化できるようになっても、互換性の問題で Dictionary の subscript set をなくすのってできないかもですねdict[key] = nil って便利構文なんじゃなくて、 subscript の仕様制約上 set を非 Optional にできなかったため仕方なくついてるものだと思ってました。 (edited)nilリテラルの代入で削除以外が起こることはないはずだから、nilリテラルの代入以外のOptionalの代入をコンパイラか別のLinterが警告する というのが妥当か。print のOptional 警告はあるから、 Dictionary の subscript set でもその線が妥当そうですね。Optional(2018)年 問題回避に役立ちますけど。CustomStringConvertible 以外できなくしちゃってもいいと思うんですよね。@nilWarning 属性みたいなものをつけられるといいのか?Optional 暗黙変換問題はどこででも起こりうるので、そういうのがあると良いのかも?@discardableResult とかと同じで Attribute 付けるとかしないとできなくないですか?enum Result { case win case lose case none } let result: Result? = .none これは暗黙変換ではなく Optional<Result>.none を入れてるだけですよね。// result : Result? = nilimport Foundation enum Computer { case win case mac } enum Result { case win case lose case none case some(Computer) } func foo(_ resultOrNil: Result?) { print(resultOrNil as Any) } foo(.win) foo(.lose) foo(.none) foo(.some(.win)) print("") foo(Result.some(.win))Optional(main.Result.win) Optional(main.Result.lose) nil Optional(main.Result.win) Optional(main.Result.some(main.Computer.win))enum Hoge { case waiwai case mu(Never) } let hoge = Hoge.waiwai switch hoge { case .waiwai: print("わいわい") }Result<Foo, Never> の switch で case .failure 書かなくても網羅的になるはず。 https://discordapp.com/channels/291054398077927425/291054454793306112/336463567039496192 "([0-9a-fA-F]+)\\.\\.([0-9a-fA-F]+);([a-zA-Z]+)" そうですねえ。i と element の片方を let 、片方を var にする方法ってありますか? let array = [2, 3, 5] for var (i, element) in array.enumerated() { print("\(i): \(element)") }let array = [2, 3, 5] for (i, var element) in array.enumerated() { element += 1 print("\(i): \(element)") }0: 3 1: 4 2: 6let array = [2, 3, 5] for (i, var element) in array.enumerated() { i += 1 element += 1 print("\(i): \(element)") }<stdin>:4:6: error: left side of mutating operator isn't mutable: 'i' is a 'let' constant i += 1 ~ ^var(let a, var b) = (2, 3)var (x, y) = (0, 0) y = 190 print(x, y) この形だとx is never mutatedの警告すら出ないですねvar にするのがいいのかな。let x: Int var y: Int (x, y) = (0, 0) 一応これは可能です。 let point: (Int, Int)? = nil if case (let x, var y)? = point { print(x, y) }static subscript って作れないのか。 @swift-4.2.4
struct S { static subscript(i: Int) -> Int { return i + 1 } }<stdin>:3:12: error: subscript cannot be marked 'static' static subscript(i: Int) -> Int { return i + 1 } ~~~~~~~^ class Container<Content> { init(a: Content) { // イニシャライザA fatalError() } init<T>(b: T) where T == Content { // イニシャライザB self.init(a: b as! Int) } } (edited)class Container<Content> { init(a: Content) { fatalError() } init<T>(b: T) where T == Content { self.init(a: b as! Int) } }<stdin>:7:27: error: same-type requirement makes generic parameters 'T' and 'Content' equivalent init<T>(b: T) where T == Content { ^ #0 0x000000000410ac94 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x410ac94) #1 0x0000000004108b22 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4108b22) #2 0x000000000410ae42 SignalHandler(int) (/usr/bin/swift+0x410ae42) #3 0x00007fdc32623390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00000000016b1b09 swift::FunctionType::get(swift::Type, swift::Type, swift::AnyFunctionType::ExtInfo const&) (/usr/bin/swift+0x16b1b09) #5 0x00000000017fde74 swift::GenericFunctionType::substGenericArgs(swift::SubstitutionMap const&) (/usr/bin/swift+0x17fde74) #6 0x00000000017fdd02 swift::GenericFunctionType::substGenericArgs(llvm::ArrayRef<swift::Substitution>) (/usr/bin/swift+0x17fdd02) #7 0x000000000147abe0 swift::UncurriedCandidate::UncurriedCandidate(swift::ValueDecl*, unsigned int) (/usr/bin/swift+0x147abe0) #8 0x000000000147f346 swift::CalleeCandidateInfo::CalleeCandidateInfo(swift::Type, llvm::ArrayRef<swift::constraints::OverloadChoice>, bool, swift::constraints::ConstraintSystem&, bool) (/usr/bin/swift+0x147f346) #9 0x0000000001466f19 (anonymous namespace)::FailureDiagnosis::visitApplyExpr(swift::ApplyExpr*) (/usr/bin/swift+0x1466f19) #10 0x000000000144d4d6 swift::ASTVisitor<(anonymous namespace)::FailureDiagnosis, bool, void, void, void, void, void>::visit(swift::Expr*) (/usr/bin/swift+0x144d4d6) #11 0x0000000001446642 swift::constraints::ConstraintSystem::diagnoseFailureForExpr(swift::Expr*) (/usr/bin/swift+0x1446642) #12 0x000000000144cb76 swift::constraints::ConstraintSystem::salvage(llvm::SmallVectorImpl<swift::constraints::Solution>&, swift::Expr*) (/usr/bin/swift+0x144cb76) #13 0x0000000001352138 swift::TypeChecker::solveForExpression(swift::Expr*&, swift::DeclContext*, swift::Type, swift::FreeTypeVariableBinding, swift::ExprTypeCheckListenwhere T == Content はダメだよって正しいエラーを吐いたあとにセグフォで死ぬのを見つけたT しか受けないことが決まっているイニシャライザAに T ではない Int を渡せちゃってる?Stack dump: 0. Program arguments: /Applications/Xcode_10_1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -interpret Development/MyPlayground.playground/Contents.swift -enable-objc-interop -sdk /Applications/Xcode_10_1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -color-diagnostics -module-name Contents 1. While type-checking 'init(b:)' at Development/MyPlayground.playground/Contents.swift:6:5 2. While type-checking statement at [Development/MyPlayground.playground/Contents.swift:6:38 - line:8:5] RangeText="{ self.init(a: b as! Int) }" 3. While type-checking expression at [Development/MyPlayground.playground/Contents.swift:7:9 - line:7:31] RangeText="self.init(a: b as! Int)" fish: 'swift Development/MyPlayground.…' terminated by signal SIGSEGV (Address boundary error)class Container<Content> { init(a: Content) { fatalError() } init<T>(b: T) where T == Content { self.init(a: b as! Int) } }<stdin>:7:27: error: same-type requirement makes generic parameters 'T' and 'Content' equivalent init<T>(b: T) where T == Content { ^ <stdin>:8:14: error: cannot invoke 'Container<Content>.init' with an argument list of type '(a: Int)' self.init(a: b as! Int) ^ <stdin>:8:14: note: expected an argument list of type '(a: Content)' self.init(a: b as! Int) ^ <stdin>:7:5: error: designated initializer for 'Container<Content>' cannot delegate (with 'self.init'); did you mean this to be a convenience initializer? init<T>(b: T) where T == Content { ^ convenience <stdin>:8:14: note: delegation occurs here self.init(a: b as! Int) ^for i in 1... { print(i) } これ無限ループになるんですね、終端値無くてもrangeになるんだfunc eatBuffer() { self.buffer = Array(self.buffer[self.pos...]) self.pos = 0 } ↑ストリーム処理を書いているときにこれをよくやりますzip(0..., arraySlice)swiftcの代わりにSourceKitを使うSwiftSyntaxだ。swiftc -> JSON -> SwiftSyntax -> SwiftLintFramework が SourceKit -> JSON -> SwiftSyntax -> SwiftLintFramework になってる。 (edited)[String: Any]ベースよりも速くなる可能性があるな。 https://github.com/apple/swift-syntax/blob/master/Sources/SwiftSyntax/ByteTreeDeserialization.swiftPackage.resolvedをコミットしていないリポジトリにいつの間にかPackage.resolvedが生成されたり、知らないうちにPackage.resolvedが更新されたりしてたりしたのが不思議だったのだけど、SourceKit-LSPを入れたVSCodeでワーキングコピーを開いてたからだった。Package.swiftの中身がLinux向けとmacOS向けで依存するライブラリが違ってて、リポジトリにはLinux向けに生成されたPackage.resolvedがコミットされてて、それをmacOSのVSCodeで開くとPackage.resolvedが更新される。swift-5.0-DEVELOPMENT-SNAPSHOT-…のmacOS版でStringのUTF16関連がぶっ壊れてるぽい。Data.withUnsafeBytes(_:)がクロージャへコピーされた一時メモリを指すポインタを渡すように変わったからだった。import Foundation let data = "test".data(using: .utf8)! dump(data) data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Void in dump(bytes) } (edited)▿ 4 bytes - count: 4 ▿ pointer: 0x00000000079af0d0 - pointerValue: 127594704 ▿ bytes: 4 elements - 116 - 101 - 115 - 116 ▿ 0x00000000079af0d0 - pointerValue: 127594704 (edited)pointerValueが違う。 $ xcrun --toolchain org.swift.5020181225a swift swift_oss_helper command enabled. Welcome to Apple Swift version 5.0-dev (LLVM c351ac7354, Clang aadec4ff83, Swift 5cfc2e7ba9). Type :help for assistance. 1> import Foundation 2. let data = "test".data(using: .utf8)! 3. dump(data) 4. data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) in 5. dump(bytes) 6. } ▿ 4 bytes - count: 4 ▿ pointer: 0x00007ffeefbff818 - pointerValue: 140732920756248 ▿ bytes: 4 elements - 116 - 101 - 115 - 116 ▿ 0x00007ffeefbffb30 - pointerValue: 140732920757040 (edited)Codableは便利ですが、FoundationのJSONEncoder, JSONDecoderを使っていて微妙に不便に感じる事があります。自分がいろいろな案件をこなしたり、他人の困り事を聞いてきた上で、...LinkedListObject周りリークしまくりでは。LinkedListObject.IndexをLinkedListObject.Node?にしたらシンプルになるのでは?と試してたのだけど、public typealias Index = Optional<Node>を定義してもCollectionにconform出来ていないと文句を言ってくる。Collection.IndexにはOptionalを使えないのかな。extension Optional: Comparable where Wrapped: Comparableになってなかった。NodeをSequenceにすると、func <が少し簡単になる。nextをfollowingに変えてる。 public static func < (lhs: LinkedListObject.Node, rhs: LinkedListObject.Node) -> Bool { if lhs == rhs || lhs.previous == rhs { return false } for following in lhs where following == rhs { return true } return false }public typealias Index = Node?案はやはり却下という結論に至った。func copyでoldIndicesに書き戻してるところは、何に使うつもりで書かれてたのですか?NodeをCollectionに。 extension LinkedListObject.Node: Collection { public enum Index: Comparable { case node(LinkedListObject.Node), none public static func < (lhs: Index, rhs: Index) -> Bool { switch (lhs, rhs) { case (.node(let lhs), .node(let rhs)): return lhs < rhs case (.node(_), .none): return true default: return false } } init(_ node: LinkedListObject.Node?) { self = node.map(Index.node) ?? .none } var node: LinkedListObject.Node? { guard case .node(let node) = self else { return nil } return node } } public var startIndex: Index { return .node(self) } public var endIndex: Index { return .none } public subscript(position: Index) -> LinkedListObject.Node { guard let node = position.node else { preconditionFailure("Index out of range") } return node } public func index(after i: Index) -> Index { guard let node = i.node, let nextIndex = node.next.map(Index.node) else { return .none } return nextIndex } }LinkedListObject.Node.IndexをLinkedListObject.Indexに。BidirectionalCollectionはLinkedListObjectで対応ですね。 extension LinkedListObject : BidirectionalCollection { public func index(before i: Index) -> Index { checkValidIndex(i) if i == endIndex { return Index(last) } precondition(i != startIndex, "Can't advance before startIndex") return Index(i.node?.previous) } }