This will allow developers to use the dollar sign for dubious purposes.
If there is a need to rewrite a Property wrapper to a macro, and keep the projectedValue, then it might make sense to write a macro that expands into a property wrapper that provides the projected value.
Otherwise, IMO it's better to use a normal English word for what the projected value essentially is, instead of using a cryptic character.
The issue raised in this thread is that macros like @Observable can't be property wrapper-aware, so macro expansion to a property wrapper would have the same problem.
A counterpoint is that property wrappers become less "magical" if we allow var $projected syntax, since macros can be used for the same source transformation.
Sorry but I didn't get it. Let's talk code instead.
Suppose we had code with a property wrapper.
@propertyWrapper struct CoolWrapper<T> {
var wrappedValue: T
var projectedValue: CoolProjection<T> { CoolProjection(wrappedValue) }
}
struct Foo {
@CoolWrapper
var bar: Int
}
print(foo.bar, foo.$bar)
For some reason we decided to rewrite the wrapper as a macro.
First rename old CoolWrapper to CoolWrapperInternal
Then introduce a macro, that will add @CoolWrapperInternal attribute to a property. (new kind of attached macro required)
@attached(attribute) // pretty much like memberAttribute but provides attributes for the attached declaration
macro CoolWrapper() = #externalMacro(...)
public struct CoolWrapperMacro: AttributeMacro {
public static func expansion<
Declaration: DeclSyntaxProtocol,
Context: MacroExpansionContext
>(
of node: AttributeSyntax,
attachedTo declaration: Declaration,
in context: Context
) throws -> [AttributeSyntax] {
return [
AttributeSyntax(attributeName: SimpleTypeIdentifierSyntax(name: .identifier("CoolWrapperInternal")))
]
}
}
As @hborla said, the property wrapper transform is applied after the macro transform, so we are safe to apply such attributes from the macro.
So
I agree. Im my Coordinator classes I tend to have more @ObservationIgnored properties than properties that are observed by default. Furthermore a plain var text = "" definition gives no indication it has been converted to a computed property but if it was required to be marked as an @ObservationTracked then that would not only provide the required indication that computation is going on but also that the underlying value can be accessed using _text e.g. during initialization. Which is an issue I see the @storageRestrictions pitch has obfuscated away from the developer.
How about making auto-tracking every property opt out, e.g. a param like @Observable(trackEveryProperty: false) for those using it for Controllers/Coordinators and not Model objects. But I fear @storageRestrictions might have already made that too complicated to implement.