SE-0258: Property Wrappers (second review)

This isn't about complaining, it's about how we can produce a language that is best for the long term. @Chris_Lattner3 has some ideas that deserve consideration. His ideas should not be excluded from consideration on their merit just because he wasn't able to offer them while Apple was building a major framework in secret on top of language features that haven't gone through SE yet.

11 Likes

They had to develop SwiftUI in a vacuum, be the language Swift has been developed in an exceptionally transparent way, with only a handful of exceptions, necessitated by the fact that Apple also has a business to run.

This is an unfair comparison and you definitely did misinterpret my feedback from above. Looking at the past few month, property wrappers popped up as property delegate which was already way different from property behaviours. The feature was highly restricted from the type declaration rules up to the usage and it used to have a totally different syntax using a by keyword. You can imagine how weird SwiftUI must have looked at that implementation state. It's the proposal authors and the communities ambition that pushed the feature into a more general design that lifted most restriction and made this feature so powerful.

SwiftUI aside, for me it would be a no brainer to choose the rocket since feature and let Apple be quiet about SwiftUI for another year until final release (if it wasn't announced already). Since this is not the case now, we're in boxed corner time wise and also marketing wise.

3 Likes

In the best of worlds, the development of Swift would be completely dictated by what is best for the long term. But Swift exists in a context, and that means it sometimes has to make compromises, and some small details of the language may not be up for discussion, even though they ideally should. But this context is also the reason Swift exists at all, and the reason that we have the richest company in the world funding our favourite language. So all in all it’s a pretty sweet deal.

With prefix you can just type $property.view instead of property$view, not a huge difference. Personally I think it is much better, we don’t need a new notational construct.

2 Likes

I agree that I could've done a better job of communicating this as the review manager. In part that's because I wasn't fully sure myself which changes would be acceptable. In this case, we did communicate in the resolution of the first review (about a month ago) that the Core Team considered a variety of things settled. The only additional thing that I think we should considered settled now is the use of $property to name an extra projection; I understand that not everyone will be pleased with that, but I think it's still compatible with quite a lot of extension and variation in this feature, and I'd like to encourage discussion along those lines.

5 Likes

I don't think this line of discussion needs to continue in this thread; let's focus on the technical proposal.

9 Likes

Again those things differ in their behaviour and types. $property returns you a specific type and then you access view. In case of the latter design property is just a plain identifier that is not yet given a functionality (if we'd return it, that's a different case). By adding $view you alter the accessor in use and access a projected value from your property wrapper type.

I highly encourage you to re-read the discussion from above starting with Chris Lattner's feedback from today to understand better what I'm trying to say here. :slight_smile:

1 Like

Without saying it's a good design:

Whatever you could put after a trailing $ you could instead put before a leading $. If Swift can generate $x for a wrapped property x, then it can also generate widget$x.

That could be made to work but it’s awkward. I think in this case the decision of prefix $ will make increase the bar additional projections need to cross in order to be a good addition to the language. Given the potential to create a “projection type” as @hartbit suggested I think it will be difficult to meet that bar. But that’s a discussion for another day if it isn’t possible to change the prefix $ at this point.

I’m saying that the wrapper writer can put

var view: SpecialView

in his wrapper type in the prefix case, which lets users access it through $property.view. In the other case, the writer writes

var $view: SpecialView

in his wrapper type and the consumer uses property$view.

What part have i misunderstood?

One counter-argument to this is that it really only works if $property "forwards" to self. If you want $property to resolve to something significantly different from the wrapper type, you can't usefully augment that with additional API that's wrapper-specific. For example, State in Swift UI wants $property to be a Binding, which is a very abstract type; if you wanted State to be able to provide a second projection (let's call it view for sake of argument), you almost certainly couldn't spell it as $property.view because you can't define view for an arbitrary Binding. So in order to support this kind of extension (1) you have to plan ahead because it can't really be done retroactively and (2) you have to make $property itself less useful as a shorthand.

4 Likes

First we're looking the third step from the above feedback.

As a reminder, the second step was to make wrapperValue more predictable as var $: Type on the wrapper type, which uses the same rules are I already mentioned several times.

In general $ prefixed members (potentially including functions in the future) will signal the compiler to project near to the wrapped property, and lastly when in use property$view to alter the way they're accessed (we're not writing property.$view on purpose as this simply wouldn't work).

Users of the module can also extend wrapper types of third party modules with their own projecting members and the compiler could make them available though every wrapped property.

extension WrapperType {
  func $doSomethingSpecial() { ... }
}

// use case
@WrapperType var something: Value

something
  $doSomethingSpecial() // cool that works

That is true. I was somewhat conflating storage and wrapper here. But if you want to project both a binding and a view you can put the view on State and it can be accessed as _property.view, while the binding will be at $property. Maybe less uniform, but there’s also less magic.

Sorry but I don’t follow you. Can you specify which part was wrong? Ignoring the wrapper/storage distinction since that’s a small detail. I mean I know that the mechanisms are different, my point is just that you can reach all the sub-properties through the wrapper/storage anyway, so you are not saving much.

This works but also undermines the "_property is private because it's only of interest to the type implementor" story.

1 Like

Sure, it’s not 100% equivalent. Though I didn’t realise that was proposed, I thought it would have the same access level as the property itself.

Is the WWDC code now use site that cannot be changed? Would this impact future language direction like Chris L. was suggesting?

If so, wouldn’t this harm the goal of world domination / widespread multi-platform support of the language if an Apple only library, Swift UI, dictates where the language goes even if it restricted the language at a later point in time?

2 Likes

Sorry John, no offence meant and sorry di it sounds rude, but you are avoiding the issue though. The issue is not that people whine about no change coming through, but that a beta framework just unveiled is mostly boxing the Swift Evolution in a corner with limited ability to influence things.

The core team is free to do decision that best benefit Apple and Apple only if it were the case, but the push to “Swift is Open Source! We have an open evolution model and we are committed to all platforms even outside Apple ones” and do not expect people believe in that and react negatively when the needs of a platform might be put before the needs of this multiplatform language.

3 Likes

I'd like to keep "grand strategy" discussions out of these review threads. (I think your question is also at least partially addressed already.)

1 Like