SE-0199: Adding toggle method to Bool

I write someLong.chained.booleanExpression() == false all the time because for long expressions, the ! at the beginning can get lost easily. toggled() would “solve” that for me

To clarify my review manager note:

toggled() is a reimplementation of ! as a function, and as such is probably on the commonly rejected proposals list. I say probably because the reasoning for rejecting that particular variant isn’t listed, but I expect we’d consider it covered by it.

Whether to add toggled() or not would also be a separate proposal that doesn’t affect whether or not a mutating toggle() should be accepted, so if it weren’t on the commonly-rejected list, it should be raised as a new pitch rather than discussed in this review.

I’m in favour of the concept but I frankly do not feel strongly either way on its inclusion, it blurs the line between being moderately useful and being too trivial to warrant its existence.

The proposed name toggle() does not feel appropriate. I think it implies that something else is happening, as if it’s a higher-level abstraction of some kind. In a GUI app context, the signature could get confused for a UI component action for example. Standard library API should be blandly named, toggle() isn’t ‘boring’ enough. invert() is my recommendation.

5 Likes

Great big +1 from me–even if for just this example. It would really improve composition with optional chaining. Yes, I could just implement this myself, but it would be nice to not have to do so for each project (personally I could get plenty of good use out of this). Not terrible if it doesn’t make it in though.

-1, agree with what @Erica_Sadun said.

David Hart mention a good argument against the name invert in the pitch thread: it is misunderstandable with number inversion. Toggle doesn’t have that problem.

1 Like

With a lot of developers that come from countries where English is not the first language. The verb that is chosen is very important as each word has a meaning which could be interchangable for English speakers, but changes meaning for others.

switch - this would not provide much context and also confuse with the already present switch statement
toggle - this would mean more like an on/off than true/false boolean.
invert - this would mean to invert the value and in the case of boolean, most appropriate
negate - this would generally mean to make negative, also indicating that there would be another method to make it positive.

so from the options above about choosing a verb, my vote is with invert

When implemented, hope that it is as fast or better than the ! operator, and if this ‘invert’ is implemented, then would the ! be open to be used for operator overloading?

I’m mildly against this proposal, echoing the sentiments of others:

  • I don’t think it’s useful enough in all or most projects to end up in the standard library
  • I don’t really agree on the name (it’s not universally applicable, just as YES and NO in ObjC often look silly)

On the plus side, someone made a point about optional chaining. This is very often an advantage of having methods like this (regardless of the underlying type) and I wonder whether it implies there is a larger point to be made about handling optionals differently in general somehow.

If the proposal was accepted for the above reason, my impression is that it’d be more Swift-like to have a non-mutating “toggled” function like this:

var myBool: Bool?
myBool = myBool?.toggled()

-1 from me, agreeing with @Erican_Sadun.

Additionally, if you have an instance where you want to toggle a property on another object, that object should give you a more descriptive method to call instead, e.g. rather than…

task.completed.toggle()

…consider…

task.complete()

Thanks to Chris Eidof for this proposal.

I’m +1 because this toggle method won’t bother me when I don’t use it, and will come in handy when appropriate. I don’t care about its name.

To go further, I wish I would read more proposals that add convenience methods in the standard lib. Being fluent (not short or terse) is good for a language, its ecosystem, its culture, and vocabulary.

2 Likes

+1.

This apprehension to adding things to the standard library is what brought us to the current (incredibly lacking) state of the standard library and Foundation).

1 Like

+1

The current manual method requires writing the reference to the object on both sides. This is wide open to misspelling mistakes, and the proposal closes the hole. (If the misspelling is total, then we get a compile error. But imagine if the misspelling pointed to another object instead. That would be very bad on the read side, and really very bad on the write side.)

Also, I’ve been playing with a packed-Bool collection type. I was thinking of including set-all, clear-all, and flip-all methods like Java’s BitSet has. The set- and clear-all methods would have single-element equivalents (just assign from true or false, respectively). Now I don’t have to worry about adding my own extension for the individual flipping case.

+1. I think it’s a clever addition to Swift that embraces its unique value-based mutation features.

3 Likes

+1.
I refuse to add that extension to my projects to avoid creating a dependency on something that’s not a part of the language. Having it built in will encourage me and others to use it.

The name toggle() doesn’t fits though. There might not be a switch behind that boolean. reverse, negate or something more generic makes more sense to me.

+1 Sound an usefull one when available trivial additive API
Could help to make source code and its logic more readable.

What does s.c here stand for? Thanks

Sorry, I edited my answer to fully write Source Code

After reading through more comments and responses from @Ben_Cohen and @Chris_Eidhof, I see there are more benefits to this than the proposal brings to light. I’d like to see the proposal updated with more of these benefits and then I would be in favor of this proposal.

I’m not sure there is a great name for this. Since this pairs with the logical NOT operator, I would prefer the term negate. It would be possible to write !boolValue.toggle() and that wouldn’t be as clearly a double-negative as !boolBalue.negate(). I would also highly support the name not(). (Even given the number of jokes to be made at our expense.) When I read code to myself in my head, I pronounce the ! operator as “not.” I think it would be good if they shared a name.

The proposed method mutates and returns Void, so this shouldn’t be possible.

So far on the thread, we’ve seen quite a few bikeshedding requests, which suggests the functionality isn’t entirely clear or best named. (For example, negate/negated aren’t bad choices here.) We’ve also seen people reaching for both mutating and non-mutating versions, to allow

  • when mutating, some.long.chain.of.access.toggle() replacing some.long.chain.of.access = !some.long.chain.of.access. This supports DRY, which is good if an esoteric use. Does this really pass the test of “If Swift were being designed today, would this be part of its stdlib?” There are some many @davedelong/MikeAsh/etc goodies I’d far prefer to see included.
  • when not mutating (currently out of scope for this proposal), simply negating, some.functional.chain.toggled() replaces !(some.functional.chain), putting the negation at the point and time of use. I guess this supports readability. One should certainly take care in linting to avoid let x = !(some.functional.chain.toggled()) as a likely bug. (And the compiler will surely catch let x = !(some.functional.chain.toggle()).

As I’ve stated before, I’m not hugely against this proposal, but I do think

  • one should avoid over-chaining (for example, where do breakpoints go?)
  • the stdlib should have a high barrier for inclusion
  • using let value = !(some.functional.chain) is not overly burdensome when chains are short. With parentheses, you emphasize negation right from the start of the chain, placing the emphasis on reversed logic that you wouldn’t have in a trailing toggled().

I remain at “more meh than yeah”.

5 Likes