I think i am having a problem using resultBuild with enums, is that normal or compile improve need?
@resultBuilder
struct ResultBuilder<T>
{
static func buildBlock(_ block: [T]...) -> [T]
{
block.flatMap { $0 }
}
....
}
enum PathModifier
{
case move(to: CGPoint)
case addLine(to: CGPoint)
case stroke
func modify(_ path: NSBezierPath)
{
switch self {
case .move(let point):
path.move(to: point)
case .addLine(let point):
path.line(to: point)
case .stroke:
path.stroke()
}
}
}
extension NSBezierPath
{
@discardableResult
convenience init(@ResultBuilder<PathModifier> _ modifiers: () -> [PathModifier])
{
self.init()
modifiers().forEach {
$0.modify(self)
}
}
@discardableResult
convenience init(modifiers: [PathModifier])
{
self.init()
modifiers.forEach {
$0.modify(self)
}
}
}
As you see, i hava above code, then if i try to write this, it would not work:
NSBezierPath {
.move(to: .zero)
.addLine(to: CGPoint(1, 1))
.stroke
}
the compile says: Enum case 'addLine' cannot be used as an instance member
But if i write like this, it works:
NSBezierPath {
PathModifier.move(to: .zero)
PathModifier.addLine(to: CGPoint(x: 1, y: 1))
PathModifier.stroke
}
and this works to:
NSBezierPath(modifiers: [
.move(to: .zero),
.addLine(to: CGPoint(x: 1, y: 1)),
.stroke
])
the problem is i like to write code more like DLS and if I have to write PathModifier each time, this would be little be bothering don't you think? It there anyway i can improve this?
The reason the compiler gives you that message is that your code is being interpreted like this (with addLine being a chained method call on move):
NSBezierPath {
.move(to: .zero).addLine(to: ...).stroke
}
This sort of problem is impossible to avoid with enum cases unless you were to put semicolons after each case (though that is disfavored, style-wise), since this syntax allows modifier methods like those of SwiftUI. Usually, I end up writing result builders, not with enum cases, but with structs, making your example look like this:
NSBezierPath {
Move(to: .zero)
Line(to: ...)
Stroke()
}
Though this doesn't read as well in your case specifically, this works better whenever you have to allow modifier methods. (Other note: I think this question would probably fit better in the "Using Swift" category)
3 Likes
Thanks, I see the point, the reason why I use enum instead strut is because this is much simpler, I don’t need to write multiple struts in this way, and namespace is another problem. I think i just keep writing PathModifier each time for now.
GreatApe
(Gustaf Kugelberg)
4
I suppose you can make global functions (move etc) that return the corresponding enum cases. Then you get the same syntax but without the points.
hisekaldma
(Jonathan Hise Kaldma)
5
There was a pitch about improving lookup in result builders to allow this sort of thing.
1 Like