Adding toggle to Bool

I tried to see if the operator resolution rules would allow two overloads for !.

  • The existing one, (Bool) -> Bool
  • A new mutating varient, (inout Bool) -> Void.

Unfortunately, I couldn't get the second overload to be called. Oddly, I didn't get an ambiguous operator error. I made a toy MyBool type to let me play with the operators:

struct MyBool {
	var value: Bool
	
	init(_ value: Bool) { self.value = value}
	
	static prefix func !(_ b: inout MyBool) {
		b.value = !b.value
	}
	
	static prefix func !(_ b: MyBool) -> MyBool {
		return MyBool(!b.value)
	}
}

extension MyBool: ExpressibleByBooleanLiteral {
	init(booleanLiteral: Bool) { self.init(booleanLiteral) }
}

extension MyBool: Equatable {
	static func ==(lhs: MyBool, rhs: MyBool) -> Bool { return lhs.value == rhs.value }
}

let t: MyBool = true
let f: MyBool = false

print(t, f)
print(!t, !f)

var trueThenFalse: MyBool = true
print("trueThenFalse starts as: \(trueThenFalse)")
!trueThenFalse // doesn't work. `!trueThenFalse as Void` does work, though
print("!trueThenFalse mutates it to: \(trueThenFalse)")
1 Like

I concur. I feel that .isTrue and .isFalse are obsoleted by the type Bool itself.

I don't feel strongly about adding or leaving out the toggle() and toggled() functions. invert() and inverted() don't make sense in my head, at least. I can't think of a situation where I'd find it obvious.

It's 8 keystrokes shorter than " == false". That's important functionality here. :slight_smile:

It feels like bad heritage from C, and it probably should be removed from Swift

I have to disagree here. ! is understood in many programming languages to represent negation. I feel like removing it now would introduce too much confusion and churn.

! does not provide any unique functionality, as it is redundant to “== false”

Like my reply above, every language that I have used has provided a way to do negation as an operator. It offers a concise way of expressing negation.

I did define toggle myself some time ago as I found it helpful.
For other methods though I believe it’s simpler to leave it to == false and avoid adding more code for options that don’t add readability. I like using prefix ! on values and == false on expressions

Glad to know I'm not the only one! I always write it like I say it, and you're right, that ! is especially hard to see when you're tired. == false makes it much more apparent.

I once thought about proposing something like the following:
var isEmpty<!>isNotEmpty: Bool

Where the compiler automatically inverts the logic when ‘isNotEmpty’ is used. This way the ! operator is not required anymore. To be honest, I’m not sure if it’s a good idea, but since we’re talking about it, I just thought I’d throw it out there.

If we’re talking about properties, I guess the compiler could generate a computed property:

So this:

var isEmpty<!>isNotEmpty: Bool

Translates to this:

var isEmpty: Bool
var isNotEmpty: Bool {
    get { return !isEmpty }
    set { isEmpty = !newValue }
}

I also meant this to be supported for local variables, but that might be more difficult to implement.

Regarding language support, this actually supports all languages. It's just the <!> (strawman syntax) that tells the compiler that the name of the inverted variable follows after it.

If this is used for every Bool, it would improve readability where they are used. I'm just not sure that it's worth the tradeoff of specifying two names for every Bool. Especially since I actually have no problems with the ! operator myself.

Is there really a movement to have a localizing compiler? Because that does not seem like something that we should be thinking or concerned about.

No one is advocating a localizing compiler.

The suggestion was something like:

variable_decl ::= "var" "<!>" ":" ... generates two boolean var declarations.

so

var foobar<!>barfoo: Bool

generates something like:

var foobar : Bool

var barfoo : Bool {

get { return !foobar }

set { foobar = !newValue }

}

Though in practice, a programmer would likely choose names like (isEmpty, isNotEmpty) instead of (foobar, barfoo).

Not a bad suggestion, but it's not something I'd recommend adding to Swift.

Elsewhere, someone may have used Ruby's metaprogramming facilities to do this, though I haven't heard of anyone doing it. One could even implement a macro in C.

1 Like

i don’t get the difference here? Swift is already in English? unless you want to tell me “for x in y” is Spanish

1 Like

The difference is keywords & syntax don’t generally inject themselves into variable names.

(Strictly speaking, I’m not sure that really applies, though, since the inverted spelling is specified by the user.)

1 Like

I’m sorry, but that’s ridiculous. Swift already has hundreds of “privileged” English properties and functions. Adding one more to Bool changes nothing. Users can still add whatever non-English identifiers they want.

Swift already also has a variety of synthesized identifiers, and will like gain more as time goes on, so I don’t really see the distinction.

Again, the idea is not to just insert 'Not' into the identifier. I thought of something like that, but also concluded that this was not suitable for people programming in other languages. The proposal lets you specify two Bool properties in one line, of which the second property is the inverse of the first. You can use any names you want for both properties, the word 'Not' has nothing to do with the proposal.

Some examples in other languages (my apologies if I butchered someones language):

var esteVacia<!>noEsteVacia: Bool
var estVide<!>nestPasVide: Bool
var istLeer<!>istNichtLeer: Bool
var isLeeg<!>isNietLeeg: Bool

Some other English examples:

var isValid<!>isInvalid: Bool
var isFast<!>isSlow: Bool

It's an interesting suggestion, although I'm not sure if it fits into Swift. In any case, this won't be in scope for the toggle proposal, so maybe we should branch off the discussion?

4 Likes

Oh wow, I totally misunderstood what was being proposed, after all. I'm onboard with this, we should make a new topic for it

I agree, we are derailing the thread. I only mentioned it because people were talking about solutions for '... == false'. I'll create a new topic and we'll see whether there is any support for this.

Let's bring the discussion back to adding a toggle() function to Bool. I totally support this and 'toggle' as name seems fine to me.

1 Like

I'm +1 for such an extension, though I'd prefer to name it invert(), as toggle() seems to be too much skeuomorphic. :upside_down_face:

4 Likes

invert is misunderstandable with number inversion.

3 Likes