Skip to content

Instantly share code, notes, and snippets.

@bok-
Created October 21, 2020 23:21
Show Gist options
  • Save bok-/07f8b691b6d0ae9bd44ea212f1fc39d4 to your computer and use it in GitHub Desktop.
Save bok-/07f8b691b6d0ae9bd44ea212f1fc39d4 to your computer and use it in GitHub Desktop.
@_functionBuilder
public enum CollectionBuilder<Component> {
// MARK: - Building Expressions
/// Basic uplift of an `Expression` into a `Component` (aka `[Expression]`)
///
public static func buildExpression(_ expression: Component) -> [Component] {
[expression]
}
/// Support for optional `Expression`s in your resut builder
///
public static func buildExpression(_ expression: Component?) -> [Component] {
[]
}
// MARK: - Building Blocks
/// Support for result builders that return no children or void
///
public static func buildBlock() -> [Component] {
[]
}
/// Support for multiple lines of `Component`s
///
public static func buildBlock(_ components: [Component]...) -> [Component] {
components.flatMap { $0 }
}
// MARK: - Building Conditionals
/// Support for single-branch conditional statements (eg an `if` statement without an `else` branch)
///
public static func buildOptional(_ components: [Component]?) -> [Component] {
components ?? []
}
/// Support for multi-branch conditional statements (eg an `if` statement with an `else` branch)
///
public static func buildEither(first: [Component]) -> [Component] {
first
}
/// Support for multi-branch conditional statements (eg an `if` statement with an `else` branch)
///
public static func buildEither(second: [Component]) -> [Component] {
second
}
/// Support for `if #available` statements, we don't really need this as we're not trying
/// to type-erase whats inside the availability statement, but @bok is a completionist so ¯\_(ツ)_/¯
///
public static func buildLimitedAvailability(_ components: [Component]) -> [Component] {
components
}
}
// MARK: - Array Support
public extension Array {
/// Initialises an Array with the results returned by a function builder
///
init(@CollectionBuilder<Element> collecting: () -> [Element]) {
self = collecting()
}
/// Adds the results of the function builder to the Array
///
mutating func collect(@CollectionBuilder<Element> _ builder: () -> [Element]) {
append(contentsOf: builder())
}
}
// MARK: - Set Support
public extension Set {
/// Initialises a Set with the results returned by a function builder
///
init(@CollectionBuilder<Element> collecting: () -> [Element]) {
self.init(collecting())
}
/// Adds the results of the function builder to the Set
///
mutating func collect(@CollectionBuilder<Element> _ builder: () -> [Element]) {
for element in builder() {
insert(element)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment