Bool also doesn’t have & and |, and as you know, && and || behave somewhat differently in terms of precedence, associativity, and short circuiting. Additionally, in Swift, the precedence of operators (and particularly of bitwise operators) has been rationalized and differ from other C-family languages.
Swift’s design also reflects the decision that Bool does not represent a bit; it represents only a logical true or false value. (By contrast, the integer types model both the integers and a sequence of bits.)
To remain consistent with this model, it would not do to add merely ^ for Bool. Either we would have to add & and | also (i.e., overturn the decision that Bool doesn’t represent a single bit, a choice that has been deliberately avoided), or we would want to create ^^ just for Bool. But if we had ^^ behave consistently with && and ||, then it would just be more or less another spelling for !=.
As you show, it’s possible to use != for this operation. Swift deliberately allows users to make their own extensions, so you can always use it for yourself, but I don’t think a ^ or ^^ would be a good fit for addition to the standard library for the reasons above.
The thing about ^^ is that it appears to imply that the operation can short circuit (for people with some C-family experience), but xor never short circuits; you always have to evaluate both arguments.
@Jonathan-Hoch Can you give a non-synthetic example of how you want to use this operator? The only real issue--for me--with != is that it doesn't have associativity defined, so you can't chain them without parentheses. But chaining more than two or three booleans together like this is relatively rare, so it would be helpful to see the use cases that are motivating your request.
I was surprised it wasn't "built in" as I was use to it in other languages.
On the one hand it makes sense for Swift to have Bool be only a logical true or false value as there are no "primitive types" in Swift. However, in other languages Bool-boolean is a primitive type and does support Bitwise operations. - This takes me back to the basics of CS. Boolean to me is the most basic bit 1-0 flipper.
To overturn Swift’s design that Bool does not represent a bit - Is "way beyond my pay grade".
This isn't quite right; to get xor, you only want to check the parity (true if there are an odd number of trues, false if even). If you already have them in a collection you can just use reduce(false, !=); the trick is when you don't have a collection.
Not just in C, but in C family languages, && and || short circuit and & and | do not. Swift is, in that respect at least, a member of the C family and the same behavior applies.
If & and | were defined for Swift, users would be justified in expecting that they do not short circuit. It would follow that since a logical XOR cannot short circuit, it would not be spelled ^^. However, it also cannot be spelled ^ because that operator is already defined with the expected precedence relative to & and | and not to && and ||.
I’m not sure to what you refer here by “looks like a XOR” other than a spelling that isn’t !=. To be clear, it is not as though users don’t know about or misunderstand != on Bool, and it both looks and behaves the same way in many languages (which is to say, it looks like != and behaves as a logical XOR in many languages). There is no evidence of user misunderstanding as to its behavior, and if it were not present in Swift it would be added to the language with the exact semantics it has.
It’s pretty clear to me that having two logical XOR operators would be problematic. Either another operator behaves identically to != in every respect for Bool values, which would then be confusing and unprecedented, or it does not because it would have different associativity and/or precedence, which would also be confusing and unprecedented.
If there is a concrete use case that isn’t well served by Swift’s current operators, we should look at what the use case is and devise another solution. Otherwise, I think it’s fair to guide users to deploy Swift’s existing operators efficaciously.
FWIW, in my own code¹, I would probably write this as:
isOn = [switch1, switch2, switch3, switch4].reduce(false, !=)
I personally find this clearer, especially if the switches are actually expressions. YMMV.
¹ at least outside of a performance-critical context; in such a context I would have to see how well the optimizer does with the expression (and maybe avoid it anyway because of debug build performance concerns).
Yes I mean that != doesn't look like XOR. I mean it isn't an XOR operator, it is a very general operator that is available for tons of types and means "not equal". If you look in the docs it's not even explained, and it is placed separately from && and || which are explained. The only mention of != is in the documentation for == where it says:
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
So I don't think it is fair to say we already have XOR. We just have an unrelated operator that happens to have the same truth table as XOR.
It might be a well known workaround among C-developers, but shouldn't Swift aim to be accessible for new developers too? At the very least the docs and the official Swift book should reflect that != is viewed as XOR I think.
Maybe I'm the only one, but I certainly didn't know of the != trick when I came to iOS development. I did come to use != sometimes when it fit the behaviour I wanted, and only several years later I realised that it was actually the same as, and an acknowledged synonym of XOR.
Maybe this is because I don't have a C background, but I think such developers will be increasingly common.
But I am not sure that it's a strong argument to say that you can get by without it. You can get by without Bool.toggle() and Int.isMultiple(of:) too, and a lot of other convenient methods recently introduced.
It's undoubtedly a workaround, since != exist independently of boolean algebra, it is not limited to Bool. I hope you can agree that it is merely a lucky accident that it has the same truth table? Just like == can be used as XNOR. Who would argue that Swift has an XNOR operator?
The question is only if it's so commonly accepted that you can expect people to know it.
Again, it's not a matter of programming language design. If a language has a Boolean type and a notion of equivalence, then this is how it works, because math. It's like asking if 1 + 1 == 2 is by design. Anyway, I think we've sufficiently explored this here.