Is it possible to create `and` and `or` extension for `Bool` type?

bitwise operations is effectively a SIMD version of bool operations. how one can't see it is beyond me )

should we used computers with 3-state "bits" with Bool's still having two states - we would live in a different world and have a different conversation.

having a different priority for bitwise ops and bool ops makes total sense of course. C didn't do it right enough (a & b == c & d didn't quite work there), swift did it right.

minimal evaluation? you meant short-circuiting or something else? for bitwise ops that wouldn't make much sense and would be rather confusing. for bools it makes total sense and allows to write, say:

a != nil && foo(a!)

which would otherwise crash without short-circuiting. if memory serves me right in the original Pascal this wasn't the case and it was fixed later on in Modula-2.

2 Likes

If the semantics are the same, why do these functions compile differently?

func f(a: Bool, b: Bool) {
    if a && b { print("hi there") }
}

func g(a: Int, b: Int) {
    if a & b > 0 { print("hi there") }
}

The first has the following code for the condition:

  test dil, 1
  je .LBB1_6
  test sil, 1
  je .LBB1_6

The latter has

  test rsi, rdi
  jle .LBB2_5

We can see that the boolean expression a && b are treated as discrete boolean values which must be tested individually. They are not combined. The expression a & b > 0 contains an explicit bitwise operation, and the compiler is smart enough to figure out that we are only testing the result against zero. If the semantics were the same, the first expression could also have used a single test dil, sil instruction, instead of testing the operands individually.

In fact, the necessity of having a comparison in g() demonstrates that a bitwise and is producing a value, and the value must be tested against some condition to determine if the expression as whole is true. In f(), each operand of && is itself a boolean expression, and may be tested individually.

you wanted UInt or change the test to != because of 0x80000000 value, but your point is understandable nevertheless. two obvious reasons: (1) short-circuiting (thus the need to test operands individually and (2) even if we remove the short-circuiting (like it was done in the original Pascal) the "SIMD" operations and normal operations can of course use different instructions.

Maybe we just have a different interpretation of what "semantic" actually means β€” I consider this to be a rather high-level concept, not something where it makes sense to look at generated assembler code...
What I consider to be the semantic of "semantic" :slight_smile: is "meaning of a word, sign β€” or even something else, like color".

Afaik it is very common to interpret zero as false and one as true, so the idea of using arbitrary numbers instead is irritating to me.
I don't consider the choices in C an implementation detail, but rather sticking with established semantics (as you pointed out, it is also common at the hardware-level).

Semantic is more powerful when you can rely on it:
When I see v * 3, without knowing anything else, I expect that there is a multiplication happening. No matter wether v is an integer, float, a quarternion or a matrix, and no matter how the assembly looks, it is always the same kind of operation.

Semantic often depends on context (* can be used with a different meaning in the context of pointers β€” and "!" also has at least two different interpretations in Swift), but in the realm of logic, "&" and "|" are clearly linked with and and or.
Btw: If you really insist that "&" and "&&" do not refer to the same concept, how do you call those operators?

1 Like

&& is a true binary operator, and & is not. This is clearly seen in that when the latter is used in an expression, each term is evaluated separately. The values of each term are never combined. This is seen at the instruction level, and is a fundamental aspect of the semantics of boolean expression building. Or to put it another way, short-circuiting is a semantic of boolean expressions, and && not only does not, but cannot, short-circuit.

semantic is above implementation details, short circuiting is not part of operator semantic... neither in swift (where short-circuitting is not a feature of the operator itself, rather it is a feature of a concrete operator function) nor in general: the precedent here is the original Pascal whose logical operations didn't circuit. also the concrete function for & can in principle short circuit (e.g. when we have 0 on the left) but i'd rather not do so.

We have been talking past each other this whole thread. Could you explain what you think the semantics of bitwise operations are and what the semantics of boolean expression operations are? Because they don't behave the same way, and they don't have the same purpose.

1 Like

" A bitwise AND is a binary operation that takes two equal-length binary representations and performs the logical AND operation on each pair of the corresponding bits". (from wikipedia)

1 Like

That's not what the && operator does in any language I am familiar with. And, in terms of semantics, you have to keep in mind that & is one of a family of operators which share a common semantic: performing a logical operations on a sequence of bits. The && operator does not share this semantic, and that is true even in C, where if a && b ... is perfectly valid, even if a and b are different lengths.

the semantic part in & is AND aka Logical conjunction. whether it operates on bits or Set<> elements or whatever else is implementation. I believe we've beaten this dead horse enough and now can agree to disagree.

1 Like

To me this boils down to the idea that a bit and a bool are semantically different. The latter represents something that is true or false, and the former is a building block in encoding of numbers and data.

It would make sense for & to operate on sequences of Bools, or tuples, or vectors. It would produce some new structure that still encapsulates truth.

However && on two numbers produce a new number. && applied to an image and a mask, produce a new image. Not a sequence of flags.

I don’t care if one or more semantically different operations would happen to produce the same assembly code or not.

1 Like

Thank you. You said better than I managed.

Now you really lost me... I just hope there's no one left who's only interested in the original topic and gets spammed with notifications about this derailed discussion ;-)

So do you actually think that operators should be switched (bitwise and should be spelled &&, and & would be defined for tuples of bools - which afair is the demand that actually started this debate)?

Edit:
Because && isn't even defined for two numbers, whereas & acts exactly as you described :thinking:

No. I’m fine with the status quo.

Honestly, I thought those inversions were just typos.

In any event, I still don't see bitwise operations and boolean expression operations as being semantically the same. For one, short-circuiting makes no sense for bitwise operations.

1 Like

this is very the point of disagreement indeed. from wikipedia:

The Wikipedia article is not conflicting with my statements. A bit, as a binary digit, can indeed represent a logical value. I'm not contending that. A bit can also represent the numbers 0 and 1. Also, it can represent Void?. It can also represent any enum with two cases and no associated values. All of these are isomorphic.

A sequence of bits can also represent a number, an image, and a plethora of other things. Or a vector of thruth-values. This doesn't change the fact that a bit-as-a-local-value and a bit-as-an-encoding-unit are semantically different things.

The set of 0 and 1 under multiplication, form a semigroup ({0, 1}, Γ—) which is isomorphic to (Bool, &&). The two structures may use the same underlying data storage β€” and the same implementation β€” but they have different semantics. One represents the logical and, and the other represents, well, numerical multiplication.

You may argue that the difference is unimportant, or that it is unnecessary to use syntax to call out the difference. That's fine, and a matter of opinion. I respect your view.

But there certainly is a difference. That's not a matter of opinion.

Is this conversation going anywhere? We're not changing && and &, and I think the original poster's question has been answered well enough.

5 Likes

No, but I've been enjoying it. Definitely doesn't belong in Using Swift, though.

2 Likes