Skip to content

Instantly share code, notes, and snippets.

@wotjd
Forked from rjchatfield/ArrayBuilder.swift
Last active February 20, 2025 12:36
Show Gist options
  • Save wotjd/80f19dbc67f0e54c24daed73378eb264 to your computer and use it in GitHub Desktop.
Save wotjd/80f19dbc67f0e54c24daed73378eb264 to your computer and use it in GitHub Desktop.
ArrayBuilder - Swift ~~FunctionBuilder~~ ResultBuilder
@resultBuilder
public struct ArrayBuilder<Element> {
public static func buildPartialBlock(first: Element?) -> [Element] { first.map { [$0] } ?? [] }
public static func buildPartialBlock(first: [Element]?) -> [Element] { first ?? [] }
public static func buildPartialBlock(first: [Element?]?) -> [Element] { (first ?? []).compactMap { $0 } }
public static func buildPartialBlock(accumulated: [Element], next: Element?) -> [Element] { accumulated + (next.map { [$0] } ?? []) }
public static func buildPartialBlock(accumulated: [Element], next: [Element]?) -> [Element] { accumulated + (next ?? []) }
public static func buildPartialBlock(accumulated: [Element], next: [Element?]?) -> [Element] { accumulated + (next ?? []).compactMap { $0 } }
// Empty Case
public static func buildBlock() -> [Element] { [] }
// If/Else
public static func buildEither(first: [Element]) -> [Element] { first }
public static func buildEither(second: [Element]) -> [Element] { second }
// Just ifs
public static func buildIf(_ element: [Element]?) -> [Element] { element ?? [] }
// fatalError()
public static func buildPartialBlock(first: Never) -> [Element] {}
}
// MARK: - Array.init(builder:)
public extension Array {
init(@ArrayBuilder<Element> builder: () -> [Element]) {
self.init(builder())
}
}
import XCTest
final class ArrayBuilderTests: XCTestCase {
let bool = false
func testExample() throws {
expect(["hello"]) {
"hello"
}
expect(["hello", "world"]) {
"hello"
"world"
}
expect(["world"]) {
if bool {
"hello"
} else {
"world"
}
}
expect(["world", "world"]) {
if bool {
"hello"
"hello"
} else {
"world"
"world"
}
}
expect(["world", "world"]) {
if bool {
"hello"
"hello"
} else if !bool {
"world"
"world"
} else {
""
}
}
expect([]) {
if bool {
"hello"
}
}
expect(["hello"]) {
if !bool {
if !bool {
"hello"
}
}
}
expect(["world"]) {
if bool {
"hello"
}
if !bool {
"world"
}
}
expect(["foo", "world"]) { // [String] or [[String]] ??
"foo" // :String
if bool {
"hello" // :String
} else {
"world" // :String
} // :[String]
}
expect(["foo", "world"]) {
["foo"]
if bool {
"hello"
} else {
"world"
}
}
expect(["world1", "world2"]) {
if bool {
"hello1"
} else {
"world1"
}
if bool {
"hello2"
} else {
"world2"
}
}
//expect(["hello"]) {
// guard bool else {
// return []
// }
// "bar"
// "baz"
//}
expect([]) {
}
func fatal() {
expect(["hello"]) {
fatalError()
}
expect(["hello"]) {
if bool {
fatalError()
}
}
expect(["hello"]) {
if bool {
fatalError()
} else {
fatalError()
}
}
// This works, just has a warning
// _ = expect(["hello"]) {
// if bool {
// "hello"
// fatalError()
// } else {
// "world"
// fatalError()
// }
// }
}
//expect(["hello"]) {
// for str in ["hello", "world"] {
// str
// }
//}
expect(["hello", "world"]) {
["hello", "world"].map { str in
str
}
}
expect(["world"]) {
switch bool {
case true: "hello"
case false: "world"
}
}
}
func test2() {
XCTAssertEqual(["hello"], Array<String>(builder: {
"hello"
}))
XCTAssertEqual(["hello", "world"], Array<String>(builder: {
"hello"
"world"
}))
XCTAssertEqual(["world"], Array<String>(builder: {
if bool {
"hello"
} else {
"world"
}
}))
XCTAssertEqual([], Array<String>(builder: {
if bool {
"hello"
}
}))
XCTAssertEqual(["world", "world"], Array<String>(builder: {
"world"
"world"
if bool {
"hello"
"optional"
}
}))
XCTAssertEqual(["world", "world"], Array<String>(builder: {
"world"
if bool {
"hello"
"optional"
}
"world"
}))
XCTAssertEqual(["world", "world"], Array<String>(builder: {
if bool {
"hello"
"optional"
}
"world"
"world"
}))
XCTAssertEqual(["world", "world"], Array<String>(builder: {
if bool {
"hello"
"optional"
}
if bool {
"hello"
"optional"
}
"world"
"world"
}))
XCTAssertEqual(["world"], Array<String>(builder: {
["world"]
if bool {
"hello"
"optional"
}
}))
}
func expect(_ expected: [String], @ArrayBuilder<String> block: () -> [String]) {
XCTAssertEqual(expected, block())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment