I don't think that's so. The proposal is for a convenience and so it is absolutely reasonable to opine on it on the basis of how often it will actually be more convenient, and also on the basis of whether we are making the wrong things more convenient, and thus encouraging poor code.
If storing optional sequences is rare and/or bad, then that's a lot of use cases where this doesn't apply or is a mistake.
For optional chaining, if string?.lines is your example of an optional sequence where this proposal would be useful, well, I'm unconvinced. Once again, existing code: (string ?? "").lines is much more straightforward about spelling out what the programmer actually wants, and we're talking about only 6 or so additional characters.
This proposal shortens things that don't need to be shortened and adds a special case for something that (in my opinion) generally only comes up when you're doing it wrong.
(As discussion has gone on and I've become more convinced of the lack of good examples here, I'd like to change my -0.5 to a strong -1.)
That's a fair point. But that's a very small use case, so I think my criticism is still valid.
I don't see how that's beneficial.
I think it's a valid criticism when considering "[if] the problem being addressed [is] significant enough to warrant a change to Swift". I'm arguing that I don't think it's significant enough because IME this pain is usually the result of poor API design or legacy APIs
I would expect "".lines to give a single, empty line, not zero lines. As I wrote before, let's not confuse nil with an empty string. It's a horrible practice.
I don't see that at all. This proposal allows you to maintain that difference, but ignore it when the effect is the same. Namely, iterating over nothing is a no-op, whether that nothing is nil or an empty sequence.
I might agree with you somewhat if the proposal was to silently treat for x in opt { } as a no-op, with no sigil or other indicator that opt may be nil.
Maybe we should simply add this information to the proposal?
This isn't the first review which questions the existence of drawbacks... also, I think there's a significant number of reviews which are positive, but prefer a different syntax - and it makes the discussion confusing when you talk about features which the proposed spelling does not have.
Could we at least agree on some sort of naming to make this easier, and include in? as another alternative?
Ya, sorry, not trying to muddy up this discussion, I was trying to see if the solution of both could be similar, and more consistent as the current workarounds are similar on first thought.
Yeah, if this proposal is accepted with for thing in seq?, I would get behind if optionalBool?. I find myself writing if maybe ?? false more than I would like.
Thank you for all your feedback so far. People mentioning that the motivation is not justified are probably right, in a sense - I realized there's a lot that hasn't been addressed in enough detail. I've updated the proposal to reflect the important parts I've read through.
Excuse my narration skills!
P.S.
I had thoughts about extending the proposal to support for-else, so that we could have a complete alternative to the main if let { for in { ... }} else { ... } example.
for element in sequence? {
...
} else {
...
}
I believe this would counter the majority of people's arguments on safety and made the motivation stronger. But that's a whole new discussion I am late for. The point is that in case of approval, for-else can be pitched anytime and perfectly fits this proposal.
That's fair, I'm just saying that the property-with-optional-collection-type case is only one use case. Therefore any argument that does not address the other use cases in fundamentally incomplete. I'm not trying to be argumentative here. I'm pointing out a weakness in the argument so those opposed may strengthen their case while the review is still open. Personally, I don't have a strong stake in the outcome.
A lot does not equal all. It does not even necessarily mean a majority. It is quite possible that there is enough value to the other (more universally valid) use cases to warrant accepting the proposal. We do not and should not design the language solely to discourage bad practices.
This was just one example. As was already pointed out, the behavior of your code is not identical with an empty lines sequence. The fact that you provided a potentially buggy example seems to support avoiding the need for workarounds like this.
There abundant examples of types and contexts where it is not possible to construct an empty sequence. I gave another example upthread of generic code constrained only to Sequence.
This is quite an overstatement IMO. I avoid storing optional collections without a strong explicit and documented reason why nil is different than empty (which is extremely rare). Yet I still run into cases where ?? [] or if let unwrapping is necessary. It isn't pervasive but it does come up on a somewhat often basis.
This is a fair criticism. Supporters of the proposal could strengthen their case by searching their code for more compelling motivating examples.
It's subjective, but I think it is somewhat easy to miss a ?? [] or ? on the end of an expression whereas for? or in? is not likely to be missed. Therefore I believe the latter increases clarity. Whether this increase in clarity is sufficient to accept the proposal is a separate question.
I don't agree with the "usually" characterization, although I would agree with "often". The difference is that this does still come up in code that does not suffer from such APIs. Optional sequences arise occasionally in a variety of valid use cases such as optional chaining, as?, try?, optional arguments with a default of nil, etc.
Imho it's worth investigating if we can accompany every use of "!" with a safe "?"-alternative (except maybe negation ;-)
If that is feasible, it would really increase simplicity in the language.
I'm slightly in favor of this proposal. I also agree that for element in sequence? { } is the spelling we should choose. It's more consistent with the rest of the language, and I think it reads more naturally.
I would be more strongly in favor of this proposal if we didn’t already have this pattern, which I think is just about as good.
guard sequence != nil else {
return
}
for element in sequence! { }
However, for situations where you want to iterate over an optional sequence without exiting early, the readability gains afforded by this proposal were nicely illustrated earlier in this thread.
I disagree that there is no problem—it’s a minor one, but the need to define shadowing local variables solely to unwrap optionals occurs frequently in Swift. These definitions are boilerplate.
Yes, you could call your non-optional local variable something else, but there’s no spelling that would elucidate anything beyond that of your original sequence. Calling the local variable unwrappedSequence or nonOptionalSequence would provide no information that isn’t already clear from its type. The declaration and need for a new scope are also an eyesore, and going through this whole dance is a potential source of confusion for developers learning Swift.
In general, if you wouldn’t have declared a local variable otherwise, readability is better if you can refer to the original optional value rather than having to declare a shadowing local variable. So I think this proposal is worth the change, if only for the specific use case of iteration without early exit.
I read through the proposal and earlier posts in the review thread. I did not follow discussion of the proposal during the pitch phase.
I'm a -1 on this proposal. In my initial deliberations, I neglected to realize that this is altering the syntax of the language. I think we should be incredibly careful about making syntactic changes to Swift, when this could just as easily be solved by 1) doing nothing or 2) adding some minor standard library support and a compiler-suggested fix-it.
Given that people with a positive attitude are inclined towards the alternative solution, how does for element in sequence? alter the language syntax? It does of course allow existing syntax in a place where it wasn't allowed before, but I have the impression you're referring to something more disruptive.
This is an option, but it has it's own drawbacks relative to a native solution, some of which are mentioned in Tino's previous replies. We also shouldn't forget about ABI stability.
Adding support for for? or in? requires a syntactic change. Adding support for a postfix ? operator is less invasive and, if this gets adopted, would be my "ideal" way of implementing this.