Title: Use strong typing instead of ruby-like `1.seconds` · Issue #4 · radex/SwiftyTimer · GitHub
Open Graph Title: Use strong typing instead of ruby-like `1.seconds` · Issue #4 · radex/SwiftyTimer
X Title: Use strong typing instead of ruby-like `1.seconds` · Issue #4 · radex/SwiftyTimer
Description: Extending Int and Double with properties second, seconds, minute, etc. seems like a rather bad idea. There's two problems with this: Anyone using your code in a project with other 3rd-party code that wants to do something similar will ha...
Open Graph Description: Extending Int and Double with properties second, seconds, minute, etc. seems like a rather bad idea. There's two problems with this: Anyone using your code in a project with other 3rd-party code th...
X Description: Extending Int and Double with properties second, seconds, minute, etc. seems like a rather bad idea. There's two problems with this: Anyone using your code in a project with other 3rd-party cod...
Opengraph URL: https://github.com/radex/SwiftyTimer/issues/4
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Use strong typing instead of ruby-like `1.seconds`","articleBody":"Extending `Int` and `Double` with properties `second`, `seconds`, `minute`, etc. seems like a rather bad idea. There's two problems with this:\n1. Anyone using your code in a project with other 3rd-party code that wants to do something similar will have a compile-time naming collision, making it impossible to use either one.\n2. It's weakly-typed. You're still taking `NSTimeInterval` as your actual time type, and all it takes is for someone to accidentally leave off the `.minutes` and they'll get the wrong time. This isn't a huge issue, as `NSTimeInterval` is used everywhere to mean seconds and people are used to it, but we can still do better.\n\nThe better approach is to use an actual `Duration` type that requires the user to type the unit as part of the constructor. With the ruby-like approach you can just say `NSTimer.after(1) { ... }` but with a proper strong type there's no way to do this. I'd suggest something like\n\n``` swift\n/// A type that represents a given duration.\npublic struct Duration: Comparable, Hashable, Printable, DebugPrintable {\n /// The time interval of the `Duration`, in seconds.\n let seconds: NSTimeInterval\n /// The time interval of the `Duration`, in minutes.\n var minutes: NSTimeInterval {\n return seconds / 60\n }\n /// The time interval of the `Duration`, in hours.\n var hours: NSTimeInterval {\n return seconds / 3600\n }\n /// The time interval of the `Duration`, in milliseconds.\n /// Sub-millisecond values are truncated.\n var milliseconds: Int64 {\n return Int64(seconds * 1_000)\n }\n /// The time interval of the `Duration`, in microseconds.\n /// Sub-microsecond values are truncated.\n var microseconds: Int64 {\n return Int64(seconds * 1_000_000)\n }\n /// The time interval of the `Duration`, in nanoseconds.\n var nanoseconds: Int64 {\n return Int64(seconds * 1_000_000_000)\n }\n\n /// Construct a `Duration` for a given number of seconds.\n public init(seconds: NSTimeInterval) {\n self.seconds = seconds\n }\n /// Construct a `Duration` for a given number of minutes.\n public init(minutes: NSTimeInterval) {\n self.init(seconds: minutes * 60)\n }\n /// Construct a `Duration` for a given number of hours.\n public init(hours: NSTimeInterval) {\n self.init(seconds: hours * 3600)\n }\n /// Construct a `Duration` for a given number of milliseconds.\n // Use Int64 because milliseconds are generally not floating-point\n // values\n public init(milliseconds: Int64) {\n self.init(seconds: NSTimeInterval(milliseconds) / 1_000)\n }\n /// Construct a `Duration` for a given number of microseconds.\n public init(microseconds: Int64) {\n self.init(seconds: NSTimeInterval(microseconds) / 1_000_000)\n }\n /// Constructs a `Duration` for a given number of nanoseconds.\n // How much tolerance does a timer actually support?\n public init(nanoseconds: Int64) {\n self.init(seconds: NSTimeInterval(nanoseconds) / 1_000_000_000)\n }\n\n public var description: String {\n // TODO: Display human-readable string with multiple units\n return toString(seconds)\n }\n\n public var debugDescription: String {\n return \"Duration(\\(seconds))\"\n }\n\n public var hashValue: Int {\n return seconds.hashValue\n }\n}\n\npublic func +(lhs: Duration, rhs: Duration) -\u003e Duration {\n return Duration(seconds: lhs.seconds + rhs.seconds)\n}\npublic func -(lhs: Duration, rhs: Duration) -\u003e Duration {\n return Duration(seconds: lhs.seconds - rhs.seconds)\n}\n// NB: Don't implement multiplication/division, that doesn't make any sense for\n// durations. As such, we don't conform to IntegerArithmeticType either.\npublic func \u003c(lhs: Duration, rhs: Duration) -\u003e Bool {\n return lhs.seconds \u003c rhs.seconds\n}\npublic func ==(lhs: Duration, rhs: Duration) -\u003e Bool {\n return lhs.seconds == rhs.seconds\n}\n```\n\nThis way you can then say `NSTimer.after(Duration(seconds: 1)) { ... }`. You could also experiment with replacing all those initializers with static functions instead (e.g. `static func seconds(seconds: NSTimeInterval)`) so that way you can say `NSTimer.after(.seconds(1)) { ... }`.\n","author":{"url":"https://github.com/lilyball","@type":"Person","name":"lilyball"},"datePublished":"2015-05-11T21:47:10.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":8},"url":"https://github.com/4/SwiftyTimer/issues/4"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:024b4385-85d5-32fa-3e1d-36a2db28996f |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | CD3A:21F2BE:501231:71E287:696A0D59 |
| html-safe-nonce | 48f2aa51ab9fe8004b7d8e5bd6dae28405e2906355090224a42c7bea01c34080 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDRDNBOjIxRjJCRTo1MDEyMzE6NzFFMjg3OjY5NkEwRDU5IiwidmlzaXRvcl9pZCI6IjkwMTU2NDU4ODM5NTk5MDM2MSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 9d80f59e4e8fbac9b60247992a755393c77c3de79ef6fb9baa1556abcf922dc8 |
| hovercard-subject-tag | issue:75370019 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/radex/SwiftyTimer/4/issue_layout |
| twitter:image | https://opengraph.githubassets.com/004847de2a9e7c90ad50f1d5c6ec9929500b91871ab05953d28d28198f415bd1/radex/SwiftyTimer/issues/4 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/004847de2a9e7c90ad50f1d5c6ec9929500b91871ab05953d28d28198f415bd1/radex/SwiftyTimer/issues/4 |
| og:image:alt | Extending Int and Double with properties second, seconds, minute, etc. seems like a rather bad idea. There's two problems with this: Anyone using your code in a project with other 3rd-party code th... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | lilyball |
| hostname | github.com |
| expected-hostname | github.com |
| None | 699227a00bbb7fe1eec276d2ae1c3a93068bc5ba483bd9dc4b2a27a8f4f2f595 |
| turbo-cache-control | no-preview |
| go-import | github.com/radex/SwiftyTimer git https://github.com/radex/SwiftyTimer.git |
| octolytics-dimension-user_id | 183747 |
| octolytics-dimension-user_login | radex |
| octolytics-dimension-repository_id | 35327084 |
| octolytics-dimension-repository_nwo | radex/SwiftyTimer |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 35327084 |
| octolytics-dimension-repository_network_root_nwo | radex/SwiftyTimer |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 7266b2d935baa1c6474b16dd9feaa5ca30607261 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width