Add toggle to Bool: spin-off discussion


(Eneko Alonso) #1

It might be too late for the discussion but I have an additional request for the proposal.

Could we add @discardableResult to toggle() and make it return the new value of the Boolean property?

Thank you,
Eneko


Accepted: SE-199 – Add `toggle` to `Bool`
(Saagar Jha) #2

If this was added, I’d prefer it to be under a different name; e.g. toggled, to match things like sort/sorted.


#3

You might want to write your argument for why this change should be made, if this is the appropriate place for that discussion.


(Eneko Alonso) #4

The main argument backing this proposal is to remove duplication of code, which prevents syntax errors, specially when indices are used.

The expression:

property.listOfStuff[0].otherProperty.theBoolean = !property.listOfStuff[0].otherProperty.theBoolean

will be replaced by:

property.listOfStuff[0].otherProperty.theBoolean.toggle()

This is handy, specially for cases where the value can be easily toggled by the user interacting with the user interface (eg. tapping on a button).

However, in many cases we might need to now the new value, to do other related operations. Like this:

property.listOfStuff[0].otherProperty.theBoolean.toggle()
if property.listOfStuff[0].otherProperty.theBoolean {
  // Property is ON, do something related 
}

As you can see, we completely miss the point of the proposal, which is to remove the duplicate code (specially the case where indices are used).

Having toggle() return the new value, would prevent code duplication:

let isON = property.listOfStuff[0].otherProperty.theBoolean.toggle()
if isON {
  // Property is ON, do something related 
}

While toggled() sounds like it would be consistent with other methods (like sort() vs sorted()), it would defeat the purpose of the proposal since “past tense” methods return an immutable copy and do not mutate the original value.

@discardableResult allows the method to be mutating, which allows the method to return the new value, while keeping the API naming convention consistent.

Other examples of mutating methods in the standard library that return a discardable result are:

  • Array.remove(at:)
  • Array.removeFirst()
  • Set.update(with:)
  • Set.remove(member:)
  • etc.

Regards,
Eneko


(Ben Cohen) #5

Hi @Eneko_Alonso – can you start a new thread for this on the general evolution discussion forum, rather than as a reply on the announcement? Thanks!


(Ben Cohen) #6

Turns out I can move the posts myself to a new topic, so here it is.


(Ben Cohen) #7

To add my own take:

I don’t think a version of toggle that both mutated and returned a value would be a good idea. It would seem similar to the pre-/post-increment operators in that there is confusion about whether the returned value is before or after the toggling, and would encourage fairly obfuscated code that combined checking a condition and altering it at the same time.

This is different from operations like removeLast which are clear in what they are returning, and which fit more naturally into clear code (e.g. while let x = a.popLast() { ... })