[Proposal] Logical augmented assigment operators

Hi there,

either I am missing out something, or it simply isn’t there. Sorry if I just missed it.

In Kotlin we have augmented assignment operators with +, -, /, * and %. This is great. We can do this:

var counter = 0
for(i in 0..10)
{
    counter += 2 * i
}

But there are no augmented logical assignment operators (available in Java), to do this:

var everythingFine = true
var individualOks = arrayOf(true, true, true, true, true, false, true)

// Check if every individual is fine
for(ok in individualOks)
{
    everythingFine &= ok
}

println(everything fine) // prints ~$ false

This would be great at least for (the ones, Java supports, too)

  • |= or
  • &= and

Additionally, you could think about adding

  • !&= not and
  • xor= exclusive or

They could be defined this way:

operator fun andAssign(other: Boolean) { this = this && other }

operator fun nandAssign(other: Boolean) { this = !(this && other) }

operator fun orAssign(other: Boolean) { this = this || other }

operator fun xorAssign(other: Boolean) { this = this xor other }

operator fun norAssign(other: Boolean) { this = !(this || other) }

Thanks for your interest :slight_smile:
Cheers,
Gem

Off-topic: There is a function to test if a predicate holds for all elements of an iterable: all - Kotlin Programming Language

Your example code can also be written as:

val everythingFine = individualOks.all { it }

Thanks. I know. Just wanted to give a very simple example for the augmented operators :wink:

nand, nor and xor are not operators, regarding your proposal I don’t see the use case.

Even if they are not operators, they will be useful. At least &= and |= should be beyond question.

1 Like

I might be wrong here, but don’t &= and |= normally represent the bitwise operation and not the boolean operation. This would make kotlin very inconsistent, having bitwise assignment operators but no normal bitwise operators.
So I don’t think they should be a part of kotlin as long as we don’t have bitwise operators. Whether they are a good idea is another discussion (and I’m not sure if I like them or not).

That’s the Java notion. To keep it consistent &&= and ||= could be an alternative.

I strongly believe Java is using the bitwise Boolean operators for &= and |=.

What about a generic assignment operator for infix operators?

val a: Foo
val b: Bar
a fn= b
class Foo{
    infix fun fn(b: Bar): Foo
}

Do you have actual example where you use it more than twice in one piece of code?

1 Like

I use it quite often, to check whether requirements in a complex context are met. I think the most useful aspect is shortness and tidier code. It’s the same like writing

a1 = a1 + a2

instead of

a1 += a2

Checks do not usually require assignment. Could you give a reference to actual piece of code?

I’ll let you know, as soon as I stumble upon it again. Just noticed, that I had to replace lots of &= and |= occurences when porting my projects from Java 1.8 to Kotlin. Mostly simple assignments like:

private boolean teamFit = true;

public void OnAttack(Monster defender, int damage)
{
    teamFit &= defender.isFit()
}

I don’t believe that a &&= b notation is a good idea.
If it would have short-circuiting behaviour, it may be not obvious that f() will not be evaluated in a &&= f() when a is false.
If there’s no short-circuiting behaviour, a &&= f() won’t be the same as a = a && f().

2 Likes

I tried to use the |= operator in Kotlin yesterday (as I have been accustomed to doing in C, C++, and Java) and was surprised to find that it didn’t exist. The fact that &= and |= don’t exist seems like a strange omission to me, and just one more thing that I have to remember when comparing Kotlin to Java, C, and C++. I don’t see an advantage to leaving these out when +=, -=, etc. operators exist. Booleans are just as important as integers for many programs, and I think they should be able to be accessed in the same ways.

2 Likes

My experience is that boolean augmented-assignments can quite commonly be useful handling pluralities eg. in framework code & data structures.

var changed = false
for (it in items) {
    changed |= add(it)
}

Does Kotlin have such clear and concise meaning in an existing syntax?

There was an OT suggestion of Iterable.all(), but that’s too high-level for framework use; 1) in terms of already implementing short-circuiting behavior, and 2) performance overhead. I would be open to considering an |= and perhaps &= operator.

changed = items.firstOrNull { add(it) } != null
should do.

It might not be the most idiomatic Kotlin ever, however you can write your own extension method to do that, and give it a name you like.

1 Like

@al3c Your code does something different, though.

The for loop will call add() for all items in the list (and set changed if any of them return true).

However, the firstOrNull() will probably stop after the first add() call that returns true; it won’t add any remaining items.

Of course, if add() had no side-effects, then the end result would be the same in both cases… But it’s a fair bet that it does have side-effects — and in fact those side-effects are probably its main purpose; if so, the ‘optimisation’ of firstOrNull() would be a big problem here!

I thought OP wanted short-circuiting.

If you don’t want it it’s even easier:
changed = items.map{ add(it) }.any()

1 Like

I think you meant

changed = items.map { add(it) }.any { it }

:slight_smile:
[ false ].any() == true.