{"id":15038582,"url":"https://github.com/davdroman/swift-builders","last_synced_at":"2025-04-09T23:41:36.629Z","repository":{"id":37862167,"uuid":"501765319","full_name":"davdroman/swift-builders","owner":"davdroman","description":"Result builders for Swift and Foundation types","archived":false,"fork":false,"pushed_at":"2024-07-10T13:19:52.000Z","size":91,"stargazers_count":13,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-02T21:45:41.688Z","etag":null,"topics":["array","builder","data","dictionary","resultbuilder","set","string","substring","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davdroman.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-09T18:24:58.000Z","updated_at":"2024-09-03T09:03:01.000Z","dependencies_parsed_at":"2024-07-10T14:28:44.873Z","dependency_job_id":null,"html_url":"https://github.com/davdroman/swift-builders","commit_stats":{"total_commits":42,"total_committers":1,"mean_commits":42.0,"dds":0.0,"last_synced_commit":"f09e2a6981a56be6cfec7b482e328eaadd07f972"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davdroman%2Fswift-builders","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davdroman%2Fswift-builders/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davdroman%2Fswift-builders/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davdroman%2Fswift-builders/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davdroman","download_url":"https://codeload.github.com/davdroman/swift-builders/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248131468,"owners_count":21052819,"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":["array","builder","data","dictionary","resultbuilder","set","string","substring","swift"],"created_at":"2024-09-24T20:39:02.458Z","updated_at":"2025-04-09T23:41:36.601Z","avatar_url":"https://github.com/davdroman.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Swift Builders\n\n[![CI](https://github.com/davdroman/swift-builders/actions/workflows/ci.yml/badge.svg)](https://github.com/davdroman/swift-builders/actions/workflows/ci.yml)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fdavdroman%2Fswift-builders%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/davdroman/swift-builders)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fdavdroman%2Fswift-builders%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/davdroman/swift-builders)\n\nA collection of useful result builders for Swift and Foundation value types.\n\n## Motivation\n\nArrays, dictionaries, and other collection-based types in Swift are relatively simple to construct and mutate.\n\nHowever, things get tricky when the contained elements depend on certain conditions or awkward logic. A prime example of this is constructing a payload to send to an analytics service. The resulting code might look like this:\n\n```swift\nfunc checkoutAnalyticsEvent(didSucceed: Bool, purchaseAmount: Decimal, userId: String?) -\u003e [String: String] {\n    var event: [String: String] = [:]\n    event[\"success\"] = didSucceed ? \"true\" : \"false\"\n    if purchaseAmount \u003e 0 {\n        event[\"amount\"] = purchaseAmount.formatted(.number.precision(.fractionLength(2)))\n    } else {\n        event[\"isFree\"] = \"true\"\n    }\n    if let userId = userId {\n        event[\"userId\"] = userId\n    } else {\n        event[\"isGuest\"] = \"true\"\n    }\n    return event\n}\n```\n\nIt's not bad, but it's definitely not as Swifty as one would expect.\n\nWe're sprinkling imperative code on what should just be a description of our payload. Not only does this make it harder to reason about the code at a glance, but it also leaves too much leeway for unintended mutations.\n\nThankfully, there's a better way...\n\n## Getting started\n\nSwift Builders enables result builder syntax for most `Collection` types in Swift and Foundation.\n\nFor example, by leveraging `Dictionary.build`, our use case above becomes:\n\n```swift\nimport Builders\n\nfunc checkoutAnalyticsEvent(didSucceed: Bool, purchaseAmount: Decimal, userId: String?) -\u003e [String: String] {\n    return [String: String].build {\n        [\"success\": didSucceed ? \"true\" : \"false\"]\n        if purchaseAmount \u003e 0 {\n            [\"amount\": purchaseAmount.formatted(.number.precision(.fractionLength(2)))]\n        } else {\n            [\"isFree\": \"true\"]\n        }\n        if let userId = userId {\n            [\"userId\": userId]\n        } else {\n            [\"isGuest\": \"true\"]\n        }\n    }\n}\n```\n\nWe can even annotate our function with the `@DictionaryBuilder` attribute to make the function body behave like the builder body itself (think `@ViewBuilder`):\n\n```swift\nimport Builders\n\n@DictionaryBuilder\u003cString, String\u003e\nfunc checkoutAnalyticsEvent(didSucceed: Bool, purchaseAmount: Decimal, userId: String?) -\u003e [String: String] {\n    [\"success\": didSucceed ? \"true\" : \"false\"]\n    if purchaseAmount \u003e 0 {\n        [\"amount\": purchaseAmount.formatted(.number.precision(.fractionLength(2)))]\n    } else {\n        [\"isFree\": \"true\"]\n    }\n    if let userId = userId {\n        [\"userId\": userId]\n    } else {\n        [\"isGuest\": \"true\"]\n    }\n}\n```\n\nThis is only a small demonstration of the power of result builders applied to Swift's native types.\n\nThe library offers a variety of builders out of the box:\n\n- `ArrayBuilder`\n- `ArraySliceBuilder`\n- `ContiguousArrayBuilder`\n- `DataBuilder`\n- `DictionaryBuilder`\n- `SetBuilder`\n- `SliceBuilder`\n- `StringBuilder`\n- `StringUTF8ViewBuilder`\n- `StringUnicodeScalarViewBuilder`\n- `SubstringBuilder`\n- `SubstringUTF8ViewBuilder`\n- `SubstringUnicodeScalarViewBuilder`\n\n## Benchmarks\n\n```\nMacBook Pro (14-inch, 2021)\nApple M1 Pro (10 cores, 8 performance and 2 efficiency)\n32 GB Memory\n\n$ swift run -c release Benchmarks\n\nname                              time        std        iterations\n-------------------------------------------------------------------\nArray\u003cAny\u003e.build                  1833.000 ns ±   7.60 %     757726\nArray\u003cInt\u003e.build                   542.000 ns ±  15.49 %    1000000\nArray\u003cInt?\u003e.build                  709.000 ns ±   9.51 %    1000000\nArraySlice\u003cAny\u003e.build             2750.000 ns ±   5.28 %     511759\nArraySlice\u003cInt\u003e.build              875.000 ns ±   8.40 %    1000000\nArraySlice\u003cInt?\u003e.build            1167.000 ns ±  13.55 %    1000000\nContiguousArray\u003cAny\u003e.build        1917.000 ns ±  12.37 %     729365\nContiguousArray\u003cInt\u003e.build         542.000 ns ±  23.24 %    1000000\nContiguousArray\u003cInt?\u003e.build        750.000 ns ±  13.97 %    1000000\nData.build                         875.000 ns ±  13.55 %    1000000\nDictionary\u003cString, Any\u003e.build     4209.000 ns ±   6.26 %     328025\nDictionary\u003cString, Double\u003e.build  2459.000 ns ±  11.92 %     562007\nDictionary\u003cString, Double?\u003e.build 2583.000 ns ±   5.51 %     526636\nSet\u003cAny\u003e.build                    6333.000 ns ±  10.30 %     228224\nSet\u003cInt\u003e.build                     750.000 ns ±  11.22 %    1000000\nSet\u003cInt?\u003e.build                   1292.000 ns ±  11.42 %    1000000\nSlice\u003cArray\u003cAny\u003e\u003e.build           2209.000 ns ±   4.95 %     629537\nSlice\u003cArray\u003cInt\u003e\u003e.build            584.000 ns ±  17.10 %    1000000\nSlice\u003cArray\u003cInt?\u003e\u003e.build           917.000 ns ±   8.49 %    1000000\nString.build                       500.000 ns ±   8.91 %    1000000\nString.UnicodeScalarView.build    3958.000 ns ±   3.04 %     351918\nString.UTF8View.build              542.000 ns ±  10.33 %    1000000\nSubstring.build                   1709.000 ns ±   4.41 %     810685\nSubstring.UnicodeScalarView.build 5084.000 ns ±   3.19 %     274560\nSubstring.UTF8View.build          1333.000 ns ±   5.89 %    1000000\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavdroman%2Fswift-builders","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavdroman%2Fswift-builders","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavdroman%2Fswift-builders/lists"}