https://forums.swift.org/t/pitch-control-flow-negation-statements/22447 Swift Forums Pitch: Control Flow Negation Statements Evolution Pitches april-fools harlanhaskins (Harlan Haskins) April 1, 2019, 2:46pm #1 Hi swift-evolution, I've been working on a pitch I think you're all going to love, as well as the corresponding implementation --------------------------------------------------------------------- Control Flow Negation Statements * Proposal: SE-NNNN * Author: Harlan Haskins * Review Manager: TBD * Status: Awaiting review * Implementation: apple/swift#23704 Introduction This proposal adds negated forms of the various control-flow operations in the Swift language. Specifically, it introduces negated forms of if, guard, while, do, and defer. Motivation Swift is a uniquely expressive language, but there are still places where boilerplate is necessary. One egregious example of missing syntactic sugar revolves around condition negation. Frequently, developers want to conditionalize their code on a condition they intend to be false. Swift has a prefix operator, !, that allows for negating a boolean, but this can be difficult to see when in front of a large expression, and sometimes requires parentheses around nested logical expressions. Instead, let's provide negated forms of common control flow. While we're at it, we can also add negated forms of do and defer, to complete the picture. Proposed solution I propose adding 5 new statements to Swift: ifn't, guardn't, whilen't, don't, and defern't. These will be analogues to the if, guard, while, do, and defer statement, but with the opposite semantics. Detailed design ifn't ifnt-statement - `ifn't` condition-list code-block else-clause? else-clause - `else` code-block | `else` if-statement | `else` ifn't-statement An ifn't statement executes the provided code block if the provided condition evaluates to false. There is no support for ifn't let or ifn't case statements. guardn't guardnt-statement - `guardn't` condition-list `else` code-block A guardn't statement executes the provided code block if the provided condition evaluates to true. There is no support for guardn't let or ifn't case statements. All the traditional rules of guard still apply. whilen't whilent-statement - `whilen't` condition-list code-block A whilen't statement executes the provided code block repeatedly until the provided condition evaluates to true. There is no support for whilen't let or whilen't case statements. don't dont-statement - `don't` code-block A don't statement does not execute the code in the provided code block. defern't defernt-statement - `defern't` code-block A defern't statement does not schedule the code in the provided code block to be run at the end of the current execution scope. These blocks, because they are not scheduled at all, do not execute in reverse order. Source compatibility These changes are purely additive, no source changes will be necessary to adopt them. Effect on ABI stability These statements do not meaningfully affect ABI surface. Effect on API resilience These statements do not affect the API of the declarations in which they are used. Alternatives considered There are many more statements whose semantics can be negated. They are left to future proposals, as I did not want to balloon this proposal. ifn't let, guardn't let, whilen't let We could support parameter binding in negated statements. One possible implementation strategy is to only execute the block if the value could not be bound, and do not introduce the binding into the new scope. ifn't case, guardn't case, whilen't case Similar to the above, we could support pattern matching. A possible strategy could be to match all patterns except the written one, and explicitly not bind any pattern bindings. catchn't We could extend the existing catch clause to support catchn't, which will only execute if the caught error does not match the provided pattern. forn't It is unclear how this would work. Maybe this would execute if the sequence returned nil immediately, without any intermediate results. return't This could be a no-op, or this could only work for boolean return values and negate their value. 44 Likes Invert guard let scoping rex-remind (Rex) April 1, 2019, 2:54pm #2 If the goal is expressivity then I'd prefer the extra 'o' e.g. guardnot. harlanhaskins (Harlan Haskins) April 1, 2019, 2:59pm #3 The contraction is vitally important to this feature. 23 Likes fbruneau (Florent Bruneau) April 1, 2019, 2:59pm #4 Seems to me you forgot wheren't. 9 Likes Alejandro (Alejandro Alonso) April 1, 2019, 3:03pm #5 Could it make sense to redo the don't statement to read more like English? don't do { print(128) } 14 Likes tkrajacic (Thomas Krajacic) April 1, 2019, 3:08pm #6 Could we add a bottom type Always to complement Never? I will tell the compiler to always execute this code-path. We can use it inside a don't block to clearly emphasize our intentions. 10 Likes harlanhaskins (Harlan Haskins) April 1, 2019, 3:09pm #7 I would want to name it Nevern't 8 Likes tkrajacic (Thomas Krajacic) April 1, 2019, 3:09pm #8 Well, I think we'll have to bikeshed this for at least a month... 7 Likes gregtitus (Greg Titus) April 1, 2019, 3:10pm #9 I disagree with the semantics of defern't: The negation of defer is to perform the given block immediately, rather than not to perform it at all. Other than this minor quibble, huge +1. Adds very important expressivity to the language, and frankly I can't understand how we've somehow made it all the way to 5.0 without these necessary keywords. 15 Likes anthonylatsis (Anthony Latsis) April 1, 2019, 3:13pm #10 The apostrophe looks very alien to Swift though. If the main idea is to "bury" negation (!) into a keyword, maybe a separate contextual not keyword that must strictly follow a statement keyword would be more natural and have less impact on the AST model and tooling. Edit OK, I admit I literally took this seriously :sweat_smile: 1 Like tkrajacic (Thomas Krajacic) April 1, 2019, 3:14pm #11 I love the symmetry this proposal gives to the language though. I think we'll see a lot of this bleed into Foundation and hopefully even AppKit. I always wanted an @IBInlet and and boy have there been times when I needed a viewDidn'tLoad() callback! 14 Likes allevato (Tony Allevato) April 1, 2019, 3:26pm #12 I've always appreciated the unless keyword in Ruby, and I like that this proposal is moving Swift in that direction but with even more clearly understandable keywords. Swift is an expressive language and English is an expressive language, so the product of those is quite beautiful. I think we should take this opportunity to clean up some of the cruft in Swift, though. The keyword if is too short and quite easy to overlook in your code. The obvious answer here is to deprecate if and introduce unlessn't, which is quite clearly visible to the reader. 14 Likes farzadshbfn (Farzad Sharbafian) April 1, 2019, 3:53pm #13 I see the shortcoming of isn't In the proposal. 1 Like thompsonate (Nate Thompson) April 1, 2019, 4:12pm #14 Compelling proposal. However, I think it's incomplete without funcn't, which would have a nil function pointer. 2 Likes ctxppc (Constantino Tsarouhas) April 1, 2019, 4:25pm #15 # harlanhaskins: The contraction is vitally important to this feature. I tend to agree with @rex-remind. Swift's philosophy isn't terseness but clarity and expressivity. Except for don't which is arguably a term of art, I'd add the "o" to avoid confusing a novice user. ifn't et al is too academic and we're targeting the general developer public. But I'm bikeshedding at this point, I'm all +1 for this feature. 1 Like Joe_Groff (Joe Groff) April 1, 2019, 4:35pm #16 Do these statements support whomst clauses? 17 Likes realdawei (Dawei) April 1, 2019, 4:46pm #17 Heh. U got me Mapache (Andres Santiago Perez Bergquist) April 1, 2019, 4:51pm #18 I look forward to when NotificationCenter supports the addIgnorer method, which fires in a continuous loop except when the relevant notification is posted. 6 Likes avladimirov (Anton Vladimirov) April 1, 2019, 4:55pm #19 Great proposal, but the else syntax seems unnecessarily complex. It seems reasonable to extend this to the else clause such that instead of else ifn't it would be possible to use a much more succinct (and therefore significantly more clear) elsen't 3 Likes tkrajacic (Thomas Krajacic) April 1, 2019, 5:03pm #20 We absolutely need the ability to cast with asn't which returns a type of Typen't. let kermit = Muppet() if let k = kermit asn't? Fraggle { // Now `k` is of type `Fragglen't` // ahh... } Not sure about the exact ergonomics yet though :thinking: 5 Likes next page - * Home * Categories * FAQ/Guidelines * Terms of Service * Privacy Policy Powered by Discourse, best viewed with JavaScript enabled Terms of Service Privacy Policy Cookie Policy