Lets say we define a protocol
public protocol ScreenFlags {
var cornerRadius: CGFloat { get }
}
now I can implement it for example:
struct ScreenFlagsImpl: ScreenFlags {
var cornerRadius: CGFloat { return 0 }
}
or
struct ScreenFlagsImpl: ScreenFlags {
let cornerRadius: CGFloat = 0
}
I am curious about the subtle differences here and possible dangers. Which of the implementations produces smaller/cleaner code in case the cornerRadius never changes and is there a way to enforce that cornerRadius is a constant not a variable
Refer to this compiler explorer link. Right click > "reveal linked code" to inspect corresponding assembly.
Subtle Differences
Renaming the implementations to reflect their underlying mechanisms.
ScreenFlagsImplComputeduses a computed property, which compiles down to a function that returns zero.With optimizations this will get inlined, const-folded and will compile down to one or two instructions. So, a simple assignment
can compile down to a single instruction for a constant value like 0.
The value zero is not stored in the struct instances as it is not a stored property.
You get your protocol implementation basically for "free".
ScreenFlagsImplStoredstores it explicitly, and arbitrary code cannot reason that it is going to be the constant zero. So, it will be read from the memory location where the struct is stored, which will usually be one extra instruction, the first is a load from the struct instancescreenFlagsImplStored, the second is the assignment itself to the global variable.Dangers?
I do not see any memory unsafety, API misuse etc kind of dangers in either of the two approaches.
For most practical purposes the performance difference between the two should also be negligible, unless you are processing a lot of
ScreenFlagsImplobjects, and even then measure first. I would personally go for the computed property implementation since it has less overhead overall. It is also much easier for the compiler to optimize especially when you can add@inlinableand friends for cross-module optimization. Whether it's significant will have to be determined by careful measurements using well-designed benchmarks, runtime profiles etc.