map
とか filter
とか簡単に書ける Swift で書けたらすごくうれしい。データの前処理は個人的には学習プログラムを走らせる前に通すので swiftで書いても良い
@t.ae#5802 もうちょっと学習に近いところで、一部のデータをいじったり変換したりフィルタしたりするところのイメージ。images = augmentation(images)
みたいにやってるlet tensor: Tensor<N, 480, 640, 4> = ...
-1
は Swift 的に微妙では。せめて nil
だと思う。let tensor: Tensor<nil, 480, 640, 4> = ...
↑この方がいいかな。T<10, 480, 640, 4>
とかを代入するんですよね?transpose
とかでゴリゴリ入れ替えたりしてると・・・$ gyb --help
A GYB template consists of the following elements: - Literal text which is inserted directly into the output - %% or $$ in literal text, which insert literal '%' and '$' symbols respectively. - Substitutions of the form ${<python-expression>}. The Python expression is converted to a string and the result is inserted into the output. - Python code delimited by %{...}%. Typically used to inject definitions (functions, classes, variable bindings) into the evaluation context of the template. Common indentation is stripped, so you can add as much indentation to the beginning of this code as you like - Lines beginning with optional whitespace followed by a single '%' and Python code. %-lines allow you to nest other constructs inside them. To close a level of nesting, use the "%end" construct. - Lines beginning with optional whitespace and followed by a single '%' and the token "end", which close open constructs in %-lines. Example template: - Hello - %{ x = 42 def succ(a): return a+1 }% I can assure you that ${x} < ${succ(x)} % if int(y) > 7: % for i in range(3): y is greater than seven! % end % else: y is less than or equal to seven % end - The End. - When run with "gyb -Dy=9", the output is - Hello - I can assure you that 42 < 43 y is greater than seven! y is greater than seven! y is greater than seven! - The End. - '''
やさしい(やさしくない(やさしい))
(edited)continue
とか break
がうまくいかないんだけどどうすればいいかわかります?if
で分岐しかしてないからやったことないや。% for x in xs: % if x == 0: % continue % end ... % end
%
以下のところのコードは Python だということです。% { } %
の中なら break
や continue
できるけど、それだと間でコード生成できず・・・continue
できなくて if
で全体囲んでるからネストが辛い・・・。"""
によって、 Swift コードとして有効な gyb 的なものが作れないだろうか?if __children__[0].execute(__context__): break
になるようにしておいて、 continue
→ return False
, break
→ return True
に変換すればいいかな。 (edited)return
に変換するってそういうことかfor ... else
あるからきちんとやるならもっと複雑になりそう。extension
を用意して prefix func +(string: String) { print(string) }
for n in 1...20 { let inTypes = (1...n).map { "T\($0)" } let commaSeparated = inTypes.joined(separator: ", ") let arrowSeparated = inTypes.map { "(\($0))" }.joined(separator: " -> ") let nestedClosuresBegin = inTypes.map { "{ \($0.lowercased()) in " }.joined() let nestedClosuresEnd = (1...n).map { _ in " }" }.joined() +""" public func curry<\(commaSeparated), R>(_ f: @escaping (\(commaSeparated)) -> R) -> \(arrowSeparated) -> R { return \(nestedClosuresBegin)f(\(commaSeparated.lowercased()))\(nestedClosuresEnd) } """ }
public func curry<T1, R>(_ f: @escaping (T1) -> R) -> (T1) -> R { return { t1 in f(t1) } } public func curry<T1, T2, R>(_ f: @escaping (T1, T2) -> R) -> (T1) -> (T2) -> R { return { t1 in { t2 in f(t1, t2) } } } public func curry<T1, T2, T3, R>(_ f: @escaping (T1, T2, T3) -> R) -> (T1) -> (T2) -> (T3) -> R { return { t1 in { t2 in { t3 in f(t1, t2, t3) } } } } public func curry<T1, T2, T3, T4, R>(_ f: @escaping (T1, T2, T3, T4) -> R) -> (T1) -> (T2) -> (T3) -> (T4) -> R { return { t1 in { t2 in { t3 in { t4 in f(t1, t2, t3, t4) } } } } }
print
って書くのは面倒だけど+""" """
>""" """
とかのほうがそれっぽい気がする (edited)prefix operator
を作成しないといけない。+""" <html> ... <table> """ for user in users { +""" <tr> <th>\(user.id)</th> <td>\(user.name)</td> </tr> """ } +""" </table> ... </html> """
(edited)>
作ってもいいかも。users
さえ定義してやれば↑動いた。<html> ... <table> <tr> <th>123</th> <td>Chris Lattner</td> </tr> <tr> <th>456</th> <td>John McCall</td> </tr> </table> ... </html>
(edited)"""
はうれしいなぁ。 Swift 5 で async/await
も入ったらめちゃくちゃ使いやすい言語になりそうだ・・・。"""
はインデントとか改行とかよく考えられてるのもうれしい。blacklist
/ whitelist
という用語が人種を「連想させる可能性」があるから除去する。 https://github.com/apple/swift/pull/11687$ swift run
便利じゃのうImportant Use UIKit classes only from your app’s main thread or main dispatch queue, unless otherwise indicated. This restriction particularly applies to classes derived from UIResponder or that involve manipulating your app’s user interface in any way.
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert]) { granted, error in logger.error(error) if !granted { return } // これまで直に呼んで問題なく動いていたがチェッカーに指摘されたので、対応 DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } }
(edited)The main thread checker is a completely new tool in Xcode 9 and it detects violations of some commonly used APIs. And specifically it focuses on UI updates and multithreading. Some APIs require that you only use them from the main thread.
(edited)/Applications/Xcode-beta.app/Contents/Developer/usr/lib/libMainThreadChecker.dylib
… Swizzling class: WKWebInspectorWKWebView Swizzling class: WKWebsiteDataStore Swizzling class: WKWebView Swizzled 9839 methods in 324 classes.
みたいな。Process
のドキュメントを見たらcurrentDirectoryPath
がdeprecated
で、ソースを見たら@available
とかなくて、Original sourceを見たらカテゴリで書かれてた… https://developer.apple.com/documentation/foundation/process/1413110-currentdirectorypath
objective-c @interface NSTask (NSDeprecated) @property (nullable, copy) NSString *launchPath; @property (copy) NSString *currentDirectoryPath; // if not set, use current - (void)launch; + (NSTask *)launchedTaskWithLaunchPath:(NSString *)path arguments:(NSArray<NSString *> *)arguments; // convenience; create and launch @end
(edited)typealias Process = NSTask
とか生えてるのかしらSwiftでextensionごとってできましたっけ?
出来ないからSwiftのインターフェイスには反映されていない感じ。class My { } @available(*, unavailable) extension My { func hello() { print("hello") } } My().hello()
コンパイル通るけど何も怒らない- Name: NSTask SwiftName: Process Methods: - Selector: 'launchedTaskWithLaunchPath:arguments:' SwiftName: launchedProcess(launchPath:arguments:) MethodKind: Class - Selector: 'launchedTaskWithExecutableURL:arguments:error:terminationHandler:' SwiftName: run(_:arguments:terminationHandler:) MethodKind: Class - Selector: 'launchAndReturnError:' SwiftName: 'run()' MethodKind: Instance
Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/Foundation.apinotes
に書かれてる。Class Factory Methods If the Swift compiler fails to identify a class factory method, you can use the NS_SWIFT_NAME macro, passing the Swift signature of the initializer to have it imported correctly. For example: + (instancetype)recordWithRPM:(NSUInteger)RPM NS_SWIFT_NAME(init(rpm:)); If the Swift compiler mistakenly identifies a method as a class factory method, you can use the NS_SWIFT_NAME macro, passing the Swift signature of the method to have it imported correctly. For example: + (id)recordWithQuality:(double)quality NS_SWIFT_NAME(record(quality:));
deprecated
とかやめてほしい…@available
として降ってくるのが理想っぽい@interface NSTask (NSDeprecated)
って書くだけではコンパイラは何もしないと思いますね。これはそれぞれのメソッドにdeprecatedのアノテーションがいるはず。[omochi@omochi-iMac swpr]$ cat b.m #import <Foundation/Foundation.h> @interface Cat : NSObject @end @interface Cat (NSDeprecated) - (int)nya; @end @implementation Cat @end int main() { Cat * cat = [[Cat alloc] init]; return cat.nya; } [omochi@omochi-iMac swpr]$ clang -fobjc-arc b.m
@interface NSTask (NSDeprecated) @property (nullable, copy) NSString *launchPath __attribute__((deprecated("..."))); @property (copy) NSString *currentDirectoryPath __attribute__((deprecated("..."))); - (void)launch __attribute__((deprecated("..."))); + (NSTask *)launchedTaskWithLaunchPath:(NSString *)path arguments:(NSArray<NSString *> *)arguments __attribute__((deprecated("..."))); @end
@interface NSValue (NSDeprecated) /* This method is unsafe because it could potentially cause buffer overruns. You should use -getValue:size: instead. */ - (void)getValue:(void *)value; // This method will likely be deprecated in a future release @end
https://developer.apple.com/documentation/foundation/nsvalue/1415141-getvalue?language=objc 見てみるとこっこうあるもんですね。(NSDeprecated)
カテゴリを @available(*, deprecated)
として扱うっていうことですか?@available(*, unavailable) extension My {
これが通るけどnoopなのは書いておくべきだとおもいます。ClangImporterじゃないけど。(NSDeprecated)
カテゴリにも__attribute__((availability(…
があることを前提にしているぽい。 https://github.com/apple/swift/blob/master/test/Inputs/clang-importer-sdk/usr/include/AppKit.h#L49 (edited)UITableView!
だけど実はイニシャライザで付けてるのかなUIView!
か。 override var view: UIView! { didSet { print("aaaa") } }
これ書いたらそのVCに遷移する時にアプリがまるごとハングするようになった。set
と get
が両方用意されてればwillSet呼ばれるか override var view: UIView! { willSet { print("willSet") } }
↓これだとwillSetも呼ばれなくなる override var view: UIView! { willSet { print("willSet") } didSet { print("didSet") } }
class Foo { lazy var bar: Int = 0 } class Foo2: Foo { override var bar: Int { didSet { print("a") } } } Foo2().bar = 2
func foo<T: P>(a: T) -> T.A { fatalError() } struct B {} protocol P {} extension P { typealias A = B }
これがコンパイル通らないのなんでですかね 'T' does not have a member type named 'A'; did you mean 'A'? になる (edited)struct B {} protocol P {} extension P { typealias A = B } func foo<T: P>(a: T) -> T.A { fatalError() }
か func foo<T: P>(a: T) -> T.A { fatalError() } struct B {} protocol P { associatedtype A } extension P { typealias A = B }
にすると通るようになるんですが。。 (edited)extension P { typealias A = B }
これだと、Tに生えてるわけじゃない、のかと思ったけど2番めのは通るのか。Codable
とかではなく一般論として、) JSON でキーが存在しない場合とそのキーに null
が設定されている場合を区別するのってありだと思いますか?{ "foo": null, "bar": 42 }
と { "bar": 42 }
を違うものとして良いか。 (edited)let x: [String: Any] = ["a": 1, "b": Int?.none] let k = x["b"] switch k { case .some(let x): print("some") // here case .none: print("none") }
enum Foo
として設定できるようにしたい、けれども、これまでとの互換性を考えると "foo"
が省略された場合は Foo.hoge
にしたい。でも、セマンティクス上 Foo
がないということも表現したくなったので let foo: Foo?
にしたいって感じです。{"b": null}
も.someになるよという話enum Event { ... }
を作って let event: Event?
というプロパティを足したくなりました。"event"
は存在しなかったので、 "event"
を省略したときは { "event": "doubleTap" }
のように解釈したいということです。 (edited)Event?
が nil
のケースも表現したいので { "event": null }
を "event"
の省略と区別したくなった、と。Event
のnil許可をやめて、enum Event
の中に case none
を入れれば解決すると思うEvent?
だと思うんですよねぇ。Event?
であるべきケースだと思うんですよ。{ "version": 2, "event": null // いべんとがない } { "version": 2, "event": "doubleTap" // ダブルタップ } { "event": null // ダブルタップ }
(edited) "event": "none"
とやるようにするとnull
があいまいでも"none"
が設定されていることは取り出せて"none"
を含むのがあれか、tarunonの言ってる2種類の型の事か"event": null
と "event"
の省略を区別するEvent?
をやめて Event.none
を作る"version"
を足してデコード時に区別するEvent?
に変換する"event": "doubleTap"
を足す)という方法もあるか。case .hoge(let fuga):
ってしてくれるけど、ラベルついてないと case .hoge(_):
ってなってる。 (edited)try
も中がいいのかもしれないけど、 ()
が面倒で結構前に書いてしまいます。case
のときは ()
が元からあるからいいけど。throws
なのかぱっと見でわかんなくなっちゃうんですよね〜。let x = 12 switch ee { case let .a(x, y): print(x, y) default: break }
みたいなときに x が何を指しているのか不安になるので 内側派。Cat
が nil
のときと Cat?
が nil
のときがめちゃくちゃわかりにくくなりそう。public enum Download: ExpressibleByNilLiteral, Equatable { public init(nilLiteral: ()) { self = .noContent } // Simulate download in one step case content(Data) // Simulate download as byte stream case streamContent(data:Data, inChunksOf:Int) // Simulate empty download case noContent }
(edited)let hoge: Hoge? = nil
とかするともう可読性破壊される.some(nil)
とかいう激ヤバなやつもできるlet hoge: Hoge? = nil
のとき hoge
は Hoge?.none
になった。 (not Hoge?.some(nil)
)nil
で表現されてましたよね。今はなくなったけど。そういうのならありな気が。MakeFamily
って何やってるの?ただの join ? 1> ["👩", "👩", "👧", "👧"].joined(separator: "\u{200d}") $R1: String = "👩👩👧👧"
(edited)🐇 🙋 🍇 🍰 name 🔡 🐈 🆕 🍼 name 🔡 🍇🍉 🐖 🌕 🍇 😀 🍪🔤Good night, 🔤 name🍪 🍉 🐖 ☀️ 🍇 😀 🍪🔤Howdy, 🔤 name🍪 🍉 🍉 🏁 🍇 🍦 greeter 🔷🙋🆕 🔤Spencer🔤 🌕 greeter 👴 Prints “Good night, Spencer” to the console 🍉
CircleCIも申請して通ればOSSのmacOSビルドに使えるのね。
問い合わせたらfree OSS Seed plan適用してもらえた。swiftlint
をdockerベースで簡単に実行出来るよう、swiftlint
を含むdockerイメージを作成した。 https://hub.docker.com/r/norionomura/swiftlint/ (edited) linux_swift_4: docker: - image: norionomura/swiftlint:swift-4.0 steps: - checkout - run: swift test - run: mkdir -p build/reports/ - run: swiftlint lint --strict --reporter junit > build/reports/junit.xml - store_test_results: path: build/reports/
状態を持っているものはclass、ステートレスで静的に扱いたいものはstruct
が原則になるかと自分は思ってます。 なお 状態
とは メンバにアクセスした時、返る結果が冪等でなくなる要因
。 つまり、ある型のメンバにアクセスして、その結果が常に同じでないならば、それは「状態を持っている」。 状態は必ずしもプロパティであるとは限らず、も「状態を持っている」といえる。 struct Hoge { var date: Date { return Date() } }
……となると、Hogeはclassであるべきなのか? どうなの? という部分で、ちょっと悩んでしまいまして。 みなさんはどうお考えかなーと聞いてみたくなりました。append
すると count
の返り値が変わりますけど、どっちになります?var date = Date()
でないのは何か理由がありますかvar date = Date()
だと date
が冪等になります (edited)class C { var i: Int = 0 } struct S { private let c = C() var num: Int { c.i += 1; return c.i } } let s = S() // letでimmutableにしてるはずなのに、 print(s.num) // 1 print(s.num) // 2 print(s.num) // 3
structでもimmutabilityを保証できるとは限らないので、 そこも含めて、「mutating以外で冪等性が壊れかねない」意図は classにすることで表現する原則がよさそうかな、と思いましたvar date: Date { return Date() }
は、システムの時計にアクセスしているから結果が変わっているので、参照透明じゃない、外部のステートを参照しているのでステートフル、ということにはなるかとstruct Entry { var name: String var view: XxxView }
みたいに、ほぼタプルとして使う時とか状態を持つか
ベースの世界観で考えると、ViewModelは状態を持つのでclassなんですけど、 共有したいかどうか
ベースのomochiさん世界観ならstructが嵌まるんですねstruct ViewModel { enum State { ... } let state: Variable<State>(.initial) }
VMをstructにするのであれば、みたいなの普通に起こりますね Variableはclassasync / await
が入ったときにちょっとわかりにくいエラーになりそうだなstruct Stone { async mutating func addWeight() { let addValue = await readAddValue() self.weight += addValue } }
type(of: fuga) == Hoge.self
これしか思いつかなかったclass Animal {} class Cat: Animal {} let cat = Cat() cat is Animal type(of: cat) === Animal.self
こうかにゃMirror(reflecting: cat).superclassMirror!.subjectType
これはAnimal.Typeだよfunc f<X: Equatable>(_ x: X) {} f(Int.self) error: TempGround.playground:2:3: error: argument type 'Int.Type' does not conform to expected type 'Equatable'
class Animal {} class Cat: Animal {} class Robot {} func isSubclass<T>(_ object: Any, of: T.Type) -> Bool { return object is T && !(type(of: object) == T.self) } isSubclass(Cat(), of: Animal.self) isSubclass(Animal(), of: Animal.self) isSubclass(Robot(), of: Animal.self)
DispatchQueue.main.async
が ViewModel
の外側でいい気も?
(edited)isSubclass("aaa", of: NSString.self) //true isSubclass("aaa" as NSString, of: String.self) // true
func isSubclass< U: AnyObject, T: AnyObject>(_ object: U, of: T.Type) -> Bool { return object is T && !(type(of: object) == T.self) }
String fuck の対策を入れたぞstatic
にできるものがほとんどな気がする。冪等性が壊れたものを外部から持ち込まない限り mutating
でないあることと冪等性が保たれることはほぼイコールだし。 @omochimetaru の言うように参照型の値を保持する場合くらい?
struct
か class
かとか、普段の #swift でされてる話と変わらないような??
とか使えないのかな #swift? みたいな/Users/sonson/code/2tch.swift/Carthage/Build/iOS/CommonCrypto.framework/Modules/module.modulemap:2:12: error: header '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h' not found header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h" ^ /Users/sonson/Library/Mobile Documents/com~apple~CloudDocs/code/2tch.swift/Core2ch/CommonCrypto.swift:10:8: error: could not build Objective-C module 'CommonCrypto' import CommonCrypto
/Users/sonson/code/2tch.swift/Carthage/Build/iOS/CommonCrypto.framework/Modules/module.modulemap
ファイルにそのパスが書いてあると思います。/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/
に CommonCrypto.h
はありますか?Module compiled with Swift 4.0 cannot be imported in Swift 4.0.2: /Users/sonson/code/2tch.swift/Carthage/Build/iOS/RealmSwift.framework/Modules/RealmSwift.swiftmodule/arm64.swiftmodule