Declaring a Bool and its inverse counterpart in one line

In the ‘adding toggle to Bool’ topic I mentioned an idea that I once had to make usage of booleans more readable. This was not related to the topic, so it was decided to create a new topic for it.

The idea is that when declaring a Bool, you can specify a second identifier that can be used for the inverse value of the variable. Here’s an example with strawman syntax:

var isEmpty<!>isNotEmpty: Bool

With this variable, the following two lines are equal:

if isNotEmpty {...}
if !isEmpty {...}

Implementation
When it comes to properties, the implementation can easily be done by making the compiler generate a computed property for the inverse value. So, the example from above will translate to the following:

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

The idea is that this syntax can be used for any Bool. However, how the implementation for local or global variables should be done I’m not sure.

More examples

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

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

My thoughts
I feel that on one hand this fits very well with Swift, since Swift promotes readable code. On the other hand, the syntax perhaps feels a bit off and it is somewhat strange to have two identifiers refer to the same value. This is especially the case when you’re talking about local variables instead of properties.

I have to say that currently I don’t have the time to implement the idea or spend much time on a proposal, but if there is great support for it perhaps other people can do that, or I can spend some time on it in the future.

– Manolo

3 Likes

It is already trivially expressible using tuples and destructuring:

extension Bool {
    var withNegated: (Bool, Bool) {
        return (self, !self)
    }
}

let (isEmpty, isNotEmpty) = [].isEmpty.withNegated
print(isEmpty, isNotEmpty)
2 Likes

@moiseev That doesn’t seem equivalent.

Oh well. Perhaps I read it incorrectly.

If we really want to introduce syntactic sugar for this, I‘d go for something along the following:

x is empty —> x.isEmpty
x is not empty —> !x.isEmpty

However, I‘m not really convinced that we should add any new syntax here.

— Martin

2 Likes

I’m against this. It’s the addition of new syntax for a single use case and I’m not convinced that it will make code more readable than just using the ! operator.

1 Like

Commonly Rejected Changes:

Replace logical operators (&&, ||, etc.) with words like “and” and “or”, allowing non-punctuation as operators and infix functions: The operator and identifier grammars are intentionally partitioned in Swift, which is a key part of how user-defined overloaded operators are supported. Requiring the compiler to see the “operator” declaration to know how to parse a file would break the ability to be able to parse a Swift file without parsing all of its imports. This has a major negative effect on tooling support.

3 Likes

Yeah sure, custom operators using normal identifier characters are not possible at the moment.
The above syntax would have to be builtin anyway in order to transform the name of the property.
I just wanted to make clear that I prefer adding sugar for using boolean properties over sugar to declare antivalent properties.

IMO I don’t feel like this is something that should be added to the language alone. This is a relatively small feature that needs some more evidence that it is trying to solve a wide problem to convince me that it’s needed.

It also feels like something that could be brought up and solved when we get to the point of discussing a fully-fledged macro system in Swift. A sufficiently powerful macro system could provide the capabilities to express this functionality and more.

4 Likes