Skip to content

Instantly share code, notes, and snippets.

@JadenGeller
Last active March 23, 2023 08:07
Show Gist options
  • Save JadenGeller/c375fc15ad5900a0ddac4ed8ba8307a9 to your computer and use it in GitHub Desktop.
Save JadenGeller/c375fc15ad5900a0ddac4ed8ba8307a9 to your computer and use it in GitHub Desktop.
ArrayBuilder
@resultBuilder
struct ArrayBuilder<Element> {
enum Component {
case atom(Element)
case spread([Component])
}
static func buildBlock(_ elements: Component...) -> Component {
.spread(elements)
}
static func buildExpression(_ element: Element) -> Component {
.atom(element)
}
static func buildExpression(_ component: Component) -> Component {
component
}
static func buildOptional(_ component: Component?) -> Component {
component ?? .spread([])
}
static func buildEither(first component: Component) -> Component {
component
}
static func buildEither(second component: Component) -> Component {
component
}
static func buildArray(_ components: [Component]) -> Component {
.spread(components)
}
static func buildFinalResult(_ component: Component) -> [Element] {
Array(component)
}
}
extension Array {
init(_ component: ArrayBuilder<Element>.Component) {
switch component {
case .atom(let element):
self = [element]
case .spread(let components):
self = components.flatMap(Array.init)
}
}
init(@ArrayBuilder<Element> build: () -> [Element]) {
self = build()
}
}
prefix func ...<S: Sequence>(_ sequence: S) -> ArrayBuilder<S.Element>.Component {
.spread(sequence.map(ArrayBuilder.Component.atom))
}
@resultBuilder
struct ArrayBuilder<Element> {
enum Component {
case spread([Element])
}
static func buildBlock(_ components: Component...) -> Component {
ArrayBuilder.buildArray(components)
}
static func buildExpression(_ element: Element) -> Component {
.spread([element])
}
static func buildExpression(_ component: Component) -> Component {
component
}
static func buildOptional(_ component: Component?) -> Component {
component ?? .spread([])
}
static func buildEither(first component: Component) -> Component {
component
}
static func buildEither(second component: Component) -> Component {
component
}
static func buildArray(_ components: [Component]) -> Component {
.spread(components.flatMap(Array.init))
}
static func buildFinalResult(_ component: Component) -> [Element] {
Array(component)
}
}
extension Array {
init(_ component: ArrayBuilder<Element>.Component) {
switch component {
case .spread(let elements):
self = elements
}
}
init(@ArrayBuilder<Element> build: () -> [Element]) {
self = build()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment