SE-0199: Adding toggle method to Bool


#55

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


(Erica Sadun) #56

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”.


(Steven) #57

+1 I don’t see any negative impact, and I’m always in favour of standardizing common helpers many people will write. The optional chaining improvement is also great.


(Dave Abrahams) #58

negate is the only alternate spelling I would consider. We don’t have “logical inversion;” we have “logical negation.” But while that’s the technically-correct term of art, it’s probably a little confusable in common usage because people think of unary - as “negation.” The only real argument I could think of against toggle was that some people might view it as a cycle from on to off and back again (or vice versa) but the risk of that seems quite low.


(TJ Usiyan) #59

+1 from me. My argument is that it is less terse than ! and that that is good.

I tend to avoid using ! because it is too terse. One thin, easy to overlook character literally negates the meaning of an expression.

(My only nit to pick is that I would also like toggled)


(Ben Cohen) #60

The review of this proposal is now over. The core team has decided to accept the proposal as-is. There was some discussion during the review of alternative names, but the team felt that toggle was the best one offered.

During the review, there was some discussion as to whether this kind of helper method belonged in the standard library. The core team sees the following motivations for its addition:

  • commonality: the team felt that the need to toggle a nested boolean is a common one across multiple different problem domains
  • readability: the addition of this command can significantly improve readability, especially as was seen in the example of toggling a boolean in a type held as a value in a dictionary
  • consistency: while reproducing the method in user code is fairly trivial, it is good to have a consistent way of doing this across all swift codebases, rather than having multiple variants
  • correctness: there is a correctness risk when the same long path needs to appear on both sides (especially when subscripts are involved), which this method would avoid
  • performance: this didn’t come up during the review, but a mutating member operation will be more efficient (requiring only one subscript lookup) once we have the co-routine-based accessors, planned for a future release

The core team would welcome further proposals to fill in gaps like this in the standard library.


(Adrian Zubarev) #61

Now that this trivial extension is accpeted, will someone tackle isFalse for the same reasons and it‘s less terse than the prefix ! operator.


(TJ Usiyan) #62

Not sure if joking.

== false is fine for this, in my opinion, but I wouldn’t fight the addition of it much because–if I’m being honest–I am not a huge fan of prefix !.


(Chris Eidhof) #63

What’s up with all the snarky replies here (and on Twitter)? I don’t really like that trend, feels pretty hostile.

I sometimes wonder if you and others actually read and understand the proposal. It’s quite different from isFalse, and has interesting use cases. Both things has been discussed a number of times in the thread.


(Adrian Zubarev) #64

I’m not sure why you see this as hostile, especially when my reply wasn’t even sarcastic. (Maybe it sounded like that, but it wasn’t meant to be sarcastic.) Personally I would appreciate the addition of isFalse in the stdlib Bool even if it’s trivial to implement yourself, so was toggle trivial to implement. That’s the only comparison I made, so I would like to know that is so snarky about it?


(Ben Cohen) #65

As mentioned during the review, a function that purely acts as an alternative to ! is on the commonly rejected proposals list.


(Adrian Zubarev) #66

Thank you for re-clarification Ben. Much appreciated.


(Chris Eidhof) #67

Then I misinterpreted it, sorry about that.


(Adrian Zubarev) #68

No it’s fine I have not felt offended or something. It’s always good to ask though.


(Erica Sadun) #69

I hope I have not contributed to any negative feeling. I honestly don’t mind that the proposal passed.

During the review period, I mentioned that I didn’t feel it was significant enough for stdlib. That the core team not only embraced this but asked for other clever corner case proposals (“The core team would welcome further proposals to fill in gaps like this in the standard library.”) suggests that my objections were outside the team’s vision of where Swift is moving

I’d like to see a clarification of that vision so the on-forum discussions can better match where the language is heading in its next steps.


(Xiaodi Wu) #70

What I really liked about the review decision was that it enumerated five bases for accepting this proposal. A less thoughtful pitch of the same idea would have failed very quickly, but thanks to the detailed discussion here and very well-written feedback, we’ve got not only a new method, but also some new ways to evaluate future additions to the standard library. Specifically, rephrasing the feedback into question form:

  • Does the proposed addition solve a need that is common across multiple different problem domains?
  • Does it significantly improve readability?
  • Is it important to have a consistent way of doing this across all Swift codebases?
  • Is there a correctness risk to existing alternatives that the new addition would avoid?
  • Can the new addition be made more efficient than existing alternatives?

I do not imagine that this is an easy standard to meet for arbitrary additions to the standard library.


Even and Odd Integers
(Jon Hull) #71

Is toggled really just a reimplementation of ! though?

Think of the optional chaining case:

let inv = myType.optionalBool?.toggled //inv has Bool? type 

vs

let inv = !myType.optionalBool //ERROR: optionalBool not unwrapped

(Jordan Rose) #72

Without commenting on the rest of it, I will note that you can get the same effect as toggled on Optionals using map:

let inv = myType.optionalBool.map(!)

while the same is not true for the mutating toggle() method.


(Ben Cohen) #73

Right. That is, assuming you really want inv to remain optional. I suspect, especially with a boolean, you would usually want to remove optionality at the same time.


(Geordie J) #75

I still don’t understand how this fits with the Swift API Guideines. We have plenty of methods along the lines of .sort() (mutating) vs .sorted() (non-mutating). Doesn’t this proposal fly in the face of that?