Skip to content

Commit 0d09210

Browse files
authored
Describe how result builders interact with "build partial block" (#151)
The `buildPartialBlock(first:)` and `buildPartialBlock(accumulated:next:)` methods are described by the "Result-Building Methods" subsection of `@resultBuilder`, but there is no corresponding detail provided in the "Result Transformations" subsection. This adds the appropriate description, including example code which demonstrates the intended use case. The point is admittedly partly moot in Swift 5.9, given that it became possible to write a result builder that has `func buildBlock<each D: Drawable>(_ components: repeat each D) -> some Drawable`, but the `buildPartialBlock()` methods may still be a better fit for some use cases. Even if this were not the case, they still exist and should be fully documented.
2 parents 22a36b8 + d53f130 commit 0d09210

File tree

1 file changed

+82
-2
lines changed

1 file changed

+82
-2
lines changed

TSPL.docc/ReferenceManual/Attributes.md

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,7 +1868,87 @@ into code that calls the static methods of the result builder type:
18681868
>> assert(builderOptional == manualOptional)
18691869
```
18701870
-->
1871-
- A code block or `do` statement
1871+
- If the result builder implements
1872+
the `buildPartialBlock(first:)`
1873+
and `buildPartialBlock(accumulated:next:)` methods,
1874+
a code block or `do` statement becomes a call to those methods.
1875+
The first statement inside of the block
1876+
is transformed to become an argument
1877+
to the `buildPartialBlock(first:)` method,
1878+
and the remaining statements become nested calls
1879+
to the `buildPartialBlock(accumulated:next:)` method.
1880+
For example, the following declarations are equivalent:
1881+
1882+
```swift
1883+
struct DrawBoth<First: Drawable, Second: Drawable>: Drawable {
1884+
var first: First
1885+
var second: Second
1886+
func draw() -> String { return first.draw() + second.draw() }
1887+
}
1888+
1889+
@resultBuilder
1890+
struct DrawingPartialBlockBuilder {
1891+
static func buildPartialBlock<D: Drawable>(first: D) -> D {
1892+
return first
1893+
}
1894+
static func buildPartialBlock<Accumulated: Drawable, Next: Drawable>(
1895+
accumulated: Accumulated, next: Next
1896+
) -> DrawBoth<Accumulated, Next> {
1897+
return DrawBoth(first: accumulated, second: next)
1898+
}
1899+
}
1900+
1901+
@DrawingPartialBlockBuilder var builderBlock: some Drawable {
1902+
Text("First")
1903+
Line(elements: [Text("Second"), Text("Third")])
1904+
Text("Last")
1905+
}
1906+
1907+
let partialResult1 = DrawingPartialBlockBuilder.buildPartialBlock(first: Text("first"))
1908+
let partialResult2 = DrawingPartialBlockBuilder.buildPartialBlock(
1909+
accumulated: partialResult1,
1910+
next: Line(elements: [Text("Second"), Text("Third")])
1911+
)
1912+
let manualResult = DrawingPartialBlockBuilder.buildPartialBlock(
1913+
accumulated: partialResult2,
1914+
next: Text("Last")
1915+
)
1916+
```
1917+
1918+
<!--
1919+
- test: `drawing-partial-block-builder`
1920+
1921+
```swifttest
1922+
-> @resultBuilder
1923+
-> struct DrawingPartialBlockBuilder {
1924+
static func buildPartialBlock<D: Drawable>(first: D) -> D {
1925+
return first
1926+
}
1927+
static func buildPartialBlock<Accumulated: Drawable, Next: Drawable>(
1928+
accumulated: Accumulated, next: Next
1929+
) -> DrawBoth<Accumulated, Next> {
1930+
return DrawBoth(first: accumulated, second: next)
1931+
}
1932+
}
1933+
-> @DrawingPartialBlockBuilder var builderBlock: some Drawable {
1934+
Text("First")
1935+
Line(elements: [Text("Second"), Text("Third")])
1936+
Text("Last")
1937+
}
1938+
---
1939+
-> let partialResult1 = DrawingPartialBlockBuilder.buildPartialBlock(first: Text("first"))
1940+
-> let partialResult2 = DrawingPartialBlockBuilder.buildPartialBlock(
1941+
accumulated: partialResult1,
1942+
next: Line(elements: [Text("Second"), Text("Third")])
1943+
)
1944+
let manualResult = DrawingPartialBlockBuilder.buildPartialBlock(
1945+
accumulated: partialResult2,
1946+
next: Text("Last")
1947+
)
1948+
>> assert(type(of: builderBlock) == type(of: manualResult))
1949+
```
1950+
-->
1951+
- Otherwise, a code block or `do` statement
18721952
becomes a call to the `buildBlock(_:)` method.
18731953
Each of the statements inside of the block is transformed,
18741954
one at a time,
@@ -1955,7 +2035,7 @@ into code that calls the static methods of the result builder type:
19552035
This transformation is always last.
19562036

19572037
<!--
1958-
- test: `result-builder-limited-availability-broken, result-builder-limited-availability-ok`
2038+
- test: `result-builder-limited-availability-broken, result-builder-limited-availability-ok`, `drawing-partial-result-builder`
19592039
19602040
```swifttest
19612041
-> protocol Drawable {

0 commit comments

Comments
 (0)