Bird
Raised Fist0
Swiftprogramming~10 mins

Custom result builder declaration in Swift - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Custom result builder declaration
Start: Define @resultBuilder Struct
↓
Implement buildBlock and other methods
↓
Use builder in function with @resultBuilder attribute
↓
Call function with closure using builder syntax
↓
Builder methods combine closure parts
↓
Return combined result
This flow shows how to define a custom result builder, use it in a function, and how the builder methods combine closure parts into a final result.
Execution Sample
Swift
import Foundation

@resultBuilder
struct MyBuilder {
    static func buildBlock(_ components: String...) -> String {
        components.joined(separator: ", ")
    }
}

func makeSentence(@MyBuilder _ content: () -> String) -> String {
    content()
}

let sentence = makeSentence {
    "Hello"
    "world"
    "from"
    "Swift"
}
print(sentence)
This code defines a custom result builder that joins strings with commas, then uses it to build a sentence from multiple string lines.
Execution Table
StepActionInput to buildBlockResult
1Call makeSentence with closure["Hello", "world", "from", "Swift"]Calls buildBlock with these strings
2Inside MyBuilder.buildBlockcomponents = ["Hello", "world", "from", "Swift"]"Hello, world, from, Swift"
3makeSentence returnsResult from buildBlock"Hello, world, from, Swift"
4Print resultOutput stringHello, world, from, Swift
💡 All closure strings combined by buildBlock and returned as final string
Variable Tracker
VariableStartAfter buildBlockFinal
componentsN/A["Hello", "world", "from", "Swift"]["Hello", "world", "from", "Swift"]
resultN/AN/A"Hello, world, from, Swift"
Key Moments - 2 Insights
Why does buildBlock receive multiple strings as an array?
Because the closure passed to makeSentence contains multiple string expressions, the builder collects them as an array parameter in buildBlock (see execution_table step 2).
What happens if you don't mark the struct with @resultBuilder?
The compiler won't treat the struct as a builder, so the special syntax in the closure won't work and you'll get errors (the flow in concept_flow depends on @resultBuilder).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what is the input to buildBlock at step 2?
A"Hello, world, from, Swift"
B["Hello", "world", "from", "Swift"]
CAn empty array
DA single string "Hello"
💡 Hint
Check the 'Input to buildBlock' column in execution_table row 2
At which step does makeSentence return the combined string?
AStep 1
BStep 2
CStep 3
DStep 4
💡 Hint
Look at the 'Action' column for when makeSentence returns in execution_table
If you add another string "!" inside the closure, how does the buildBlock input change?
AIt includes the new string in the array
BIt becomes a single concatenated string
CIt stays the same
DIt causes a compile error
💡 Hint
Refer to how buildBlock collects all closure expressions as an array (execution_table step 2)
Concept Snapshot
@resultBuilder struct MyBuilder {
  static func buildBlock(_ components: String...) -> String {
    components.joined(separator: ", ")
  }
}

Use @MyBuilder in function parameter to build combined result from closure lines.
The builder collects closure parts and merges them in buildBlock.
Full Transcript
This example shows how to create a custom result builder in Swift. First, you define a struct marked with @resultBuilder. Inside, you implement static methods like buildBlock that take parts of the closure and combine them. Then, you use this builder in a function parameter marked with @MyBuilder. When you call the function with a closure containing multiple strings, the builder collects these strings into an array and joins them with commas. The final combined string is returned and printed. This process helps write cleaner code by letting you write multiple expressions inside a closure that get combined automatically.

Practice

(1/5)
1. What is the main purpose of declaring a @resultBuilder in Swift?
easy
A. To handle errors automatically in functions
B. To create a new data type like a class or struct
C. To optimize memory usage during runtime
D. To define how multiple code parts combine into a single result

Solution

  1. Step 1: Understand the role of @resultBuilder

    A @resultBuilder is used to customize how multiple code blocks combine into one result, making code cleaner.
  2. Step 2: Compare with other options

    Options A, B, and D describe unrelated concepts like error handling, data types, and optimization, which are not the purpose of result builders.
  3. Final Answer:

    To define how multiple code parts combine into a single result -> Option D
  4. Quick Check:

    Result builder = combine code parts [OK]
Hint: Result builders combine code parts into one result [OK]
Common Mistakes:
  • Confusing result builders with classes or structs
  • Thinking result builders handle errors
  • Assuming result builders optimize memory
2. Which of the following is the correct way to start declaring a custom result builder in Swift?
easy
A. @resultBuilder struct MyBuilder { static func buildBlock() -> String { "" } }
B. @resultBuilder class MyBuilder { func buildBlock() {} }
C. class MyBuilder { func buildBlock() -> Int { 0 } }
D. struct MyBuilder { static func buildBlock() {} }

Solution

  1. Step 1: Identify correct syntax for result builder

    A custom result builder must be declared with @resultBuilder attribute on a struct, and have static methods like buildBlock returning a value.
  2. Step 2: Check each option

    @resultBuilder struct MyBuilder { static func buildBlock() -> String { "" } } correctly uses @resultBuilder, declares a struct, and has a static buildBlock method returning a String. The other options miss the attribute, use class instead of struct, or have non-static buildBlock.
  3. Final Answer:

    @resultBuilder struct MyBuilder { static func buildBlock() -> String { "" } } -> Option A
  4. Quick Check:

    Result builder = @resultBuilder + struct + static methods [OK]
Hint: Use @resultBuilder on a struct with static buildBlock method [OK]
Common Mistakes:
  • Using class instead of struct for result builder
  • Forgetting the @resultBuilder attribute
  • Making buildBlock non-static
3. Given this custom result builder and usage, what is the output?
 @resultBuilder
struct IntSumBuilder {
    static func buildBlock(_ numbers: Int...) -> Int {
        numbers.reduce(0, +)
    }
}

func sum(@IntSumBuilder _ content: () -> Int) -> Int {
    content()
}

let result = sum {
    5
    10
    3
}
print(result)
medium
A. 5103
B. 18
C. Error: buildBlock requires array
D. 0

Solution

  1. Step 1: Understand buildBlock behavior

    The buildBlock method takes multiple Int values and sums them using reduce(0, +).
  2. Step 2: Evaluate the sum call

    The closure passed to sum returns three Int values: 5, 10, and 3. The builder sums them: 5 + 10 + 3 = 18.
  3. Final Answer:

    18 -> Option B
  4. Quick Check:

    Sum of 5, 10, 3 = 18 [OK]
Hint: buildBlock sums all Int inputs passed in closure [OK]
Common Mistakes:
  • Thinking values concatenate as strings
  • Expecting buildBlock to receive an array instead of variadic
  • Confusing output with zero or error
4. Identify the error in this custom result builder declaration:
 @resultBuilder
struct TextBuilder {
    func buildBlock(_ components: String...) -> String {
        components.joined(separator: ", ")
    }
}
medium
A. buildBlock must be static
B. buildBlock must return Int
C. struct cannot be used with @resultBuilder
D. buildBlock cannot take variadic parameters

Solution

  1. Step 1: Check method requirements in result builder

    Methods like buildBlock inside a @resultBuilder must be declared as static so they can be called without an instance.
  2. Step 2: Analyze the given code

    The buildBlock method is missing the static keyword, which causes a compile error.
  3. Final Answer:

    buildBlock must be static -> Option A
  4. Quick Check:

    buildBlock method = static [OK]
Hint: buildBlock must always be static in result builders [OK]
Common Mistakes:
  • Omitting static keyword on buildBlock
  • Thinking buildBlock must return Int always
  • Believing struct can't be used with @resultBuilder
5. You want to create a custom result builder that builds a dictionary from key-value pairs written inside a closure. Which of the following buildBlock implementations correctly combines multiple (String, Int) tuples into a single dictionary?
hard
A. static func buildBlock(_ pairs: (String, Int)...) -> [String: Int] { pairs.map { [$0.0: $0.1] } }
B. static func buildBlock(_ pairs: [(String, Int)]) -> [String: Int] { pairs.reduce([:]) { $0 + $1 } }
C. static func buildBlock(_ pairs: (String, Int)...) -> [String: Int] { Dictionary(uniqueKeysWithValues: pairs) }
D. static func buildBlock(_ pairs: (String, Int)...) -> [(String, Int)] { pairs }

Solution

  1. Step 1: Understand the goal

    The builder should combine multiple key-value pairs into a single dictionary.
  2. Step 2: Analyze each option

    static func buildBlock(_ pairs: (String, Int)...) -> [String: Int] { Dictionary(uniqueKeysWithValues: pairs) } uses Dictionary(uniqueKeysWithValues:) which correctly creates a dictionary from tuples. static func buildBlock(_ pairs: [(String, Int)]) -> [String: Int] { pairs.reduce([:]) { $0 + $1 } } tries to reduce with + which is invalid for dictionaries. static func buildBlock(_ pairs: (String, Int)...) -> [String: Int] { pairs.map { [$0.0: $0.1] } } maps to an array of dictionaries, not a single dictionary. static func buildBlock(_ pairs: (String, Int)...) -> [(String, Int)] { pairs } returns an array of tuples, not a dictionary.
  3. Final Answer:

    static func buildBlock(_ pairs: (String, Int)...) -> [String: Int] { Dictionary(uniqueKeysWithValues: pairs) } -> Option C
  4. Quick Check:

    Use Dictionary(uniqueKeysWithValues:) to combine tuples [OK]
Hint: Use Dictionary(uniqueKeysWithValues:) to build dictionary from tuples [OK]
Common Mistakes:
  • Returning array of dictionaries instead of one dictionary
  • Using invalid + operator to combine dictionaries
  • Returning array of tuples instead of dictionary
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard