{"id":20630453,"url":"https://github.com/mkj-is/noopkit","last_synced_at":"2025-09-15T20:15:39.281Z","repository":{"id":63918585,"uuid":"289750228","full_name":"mkj-is/NoopKit","owner":"mkj-is","description":"Short for No-operation Kit. Set of functions making work with empty closures a breeze.","archived":false,"fork":false,"pushed_at":"2023-07-28T14:40:46.000Z","size":80,"stargazers_count":18,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-13T20:13:44.423Z","etag":null,"topics":["functional-programming","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mkj-is.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-08-23T19:07:37.000Z","updated_at":"2024-05-02T11:59:02.000Z","dependencies_parsed_at":"2023-01-14T14:00:51.265Z","dependency_job_id":null,"html_url":"https://github.com/mkj-is/NoopKit","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkj-is%2FNoopKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkj-is%2FNoopKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkj-is%2FNoopKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkj-is%2FNoopKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mkj-is","download_url":"https://codeload.github.com/mkj-is/NoopKit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249126111,"owners_count":21216727,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functional-programming","swift"],"created_at":"2024-11-16T14:07:54.181Z","updated_at":"2025-09-15T20:15:34.238Z","avatar_url":"https://github.com/mkj-is.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"![# NoopKit](Meta/Logo.svg)\n\nShort for **No-operation Kit**. Set of functions making work with empty closures a breeze.\n\nBy empty closures we mean:\n\n- Closures not doing anything (not calling any other code).\n- Closures returning constant value.\n- Closures returning the same parameters which were passed to them.\n- More broadly closures with no side-effects.\n\n## Motivation\n\nDay by day we are using more functional programming in our apps.\nThe turning point for mainstream developer on Apple platforms was the introduction of SwiftUI.\n\nIn UIKit it was enough to write empty method or not connect IBAction in the interface builder.\nBut as you can see this has a downside, it is hard to search for an empty method or unused control.\n\nSimilarly, it is hard to search for unimplemented closures passed to higher-order functions.\nThey can be a mess of underlines, brackets and parentheses. I wanted to improve the experience\nduring active development by passing named functions, which enable us to make more readable code\nfor human and are more discoverable.\n\nThere are typical use-cases where these free functions shine:\n\n- SwiftUI previews.\n- Tests.\n- Unimplemented view bindings.\n- Unimplemented completion handlers.\n\nSecondarily, I wanted to learn Sourcery and see how variadic generics can be used in Swift until\n[proposed solution from Generics manifesto](https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#variadic-generics)\nis added to the language.\n\nAs of Swift 5.9 the implementation changed to parameter packs. Generated code is still kept to keep backward\ncompatibility for older Swift versions.\n\n## Usage examples\n\nThis library provides four free pure functions with variadic generics.\n\n### No-op\n\nCan be used either as a temporary placeholder when calling higher-order functions\nwhere no action is required. Sometimes the parameter is not optional and you need\nto pass a value.\n\n```swift\n// With anonymous closure\nURLSession.shared.dataTask(with: url) { _, _, _ in }.resume()\n// Named function\nURLSession.shared.dataTask(with: url, completionHandler: noop).resume()\n```\n\nAnother typical place for `noop` function is as a default parameter in higher order functions.\n\n```swift\n// With anonymous closure\nfunc animate(with completion: (Bool) -\u003e Void = { _ in })\n// Named function\nfunc animate(with completion: (Bool) -\u003e Void = noop)\n```\n\n### Undefined\n\nSimilar to `noop`, `undefined` is a placeholder function, but instead of doing nothing it calls\nfatal error. This function makes it clear to the developer, that it needs to be implemented.\nIt is easy to find, which is not the case for empty closures.\n\n```swift\nButton(\"Tap and crash\", action: undefined)\nStepper(\"Step to crash\", onIncrement: undefined, onDecrement: undefined)\n```\n\n### Constant\n\n`Undefined` and `noop` do not work with return values.\nConst function takes one parameter and returns a closure, which throws away all the parameters\nand constantly returns the provided value.\n\n```swift\n// Using closure\nvalidate(string: \"Some string\", using: { _ in true })\n// Using const function\nvalidate(string: \"Some string\", using: const(true))\n```\n\n### Identity\n\nIdentity (`id`) function returns all the arguments it receives as a tuple.\nThis is useful in a function with one parameter.\nTypical use-case is the `compactMap` method.\n\n```swift\n// Using closures\n[1, nil, 2, nil].compactMap { $0 }\n// Using id function\n[1, nil, 2, nil].compactMap(id)\n```\n\nAs you can see, the `id` can replace any  `{ $0 }` closure returning one anonymous parameter.\n\n## Installation\n\nAdd this package dependency to your Xcode project or add following line to your `Package.swift` file:\n\n```swift\n.package(url: \"https://github.com/mkj-is/NoopKit.git\", from: \"1.0.0\")\n```\n\nFeel free to add some of these free functions using copy \u0026 paste if you want to experiment\nand don't need the full package.\n\n## Disclosure\n\nMost of these functions are just a syntactic sugar. Be mindful when adding them\nto your project. Swift is a complicated language as is and introducing more syntactic\nsugar to your project can increase the complexity and understandability of your code.\nI personally don't use those functions on team projects, but experimentally\non my personal project. If introducing these functions to your codebase make sure\nevery contributor understands them and accepts their use.\n\n## Authors \u0026 contributing\n\nAll contributions are welcome.\n\nProject was created by [Matěj Kašpar Jirásek](https://github.com/mkj-is).\n\nProject is licensed under [MIT license](LICENSE).\n\n## Acknowledgements\n\nSome people explored similar concepts in the past, notably:\n\n- https://academy.realm.io/posts/swift-summit-johannes-weiss-the-type-system-is-your-friend/\n- https://academy.realm.io/posts/closures-api-design/\n- https://github.com/pointfreeco/swift-prelude/blob/main/Sources/Prelude/Function.swift\n- https://github.com/robrix/Prelude/blob/master/Prelude/Prelude.swift\n\nMany of the ideas come from Haskell and other functional programming languages.\n\nI iterated on their work mainly by adding „variadic generics“ using code generation.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkj-is%2Fnoopkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmkj-is%2Fnoopkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkj-is%2Fnoopkit/lists"}