Flipping a Boolean without Repeating Yourself


#1

Since Kotlin has some other somewhat adventurous constructs too, perhaps a way to “toggle a boolean” could be added - to get rid of, in long cases, a somewhat annoying “DRY” (Do not repeat yourself)?

Instead of:
myAnnoyinglyLongVariableOrExpression.enabled = !myAnnoyinglyLongVariableOrExpression.enabled

For example (off the top of my head):
flipIt myAnnoyinglyLongVariableOrExpression.enabled

In Java, this is currently possible with the (somewhat obscure) xor-operator.

Possibly the best alleviation for this (at least in my case), that I came up on Slack by someone, was:
myAnnoyinglyLongVariableOrExpression.let { it.enabled = !it.enabled }

It’s still repeating, though, and could be improved.

What do you think?


#2

Use shorter variable names.


#3
  1. This is not always possible (3rd party code).
  2. It’s not necessarily a simple, short variable, but an expression.
  3. If I use shorter variable names, someone just might come and say that use longer, more meaningful variable names… :slight_smile:

#4

Because of the way it works, this is something which you can actually do now by overloading the ++ (and/or the --) operator on the Boolean type:

operator fun Boolean.inc() = !this

class C {
    var enabled: Boolean = false
}

fun main(args:Array<String>) {
    var b = true
    b++
    println(b)   // false
    val c = C()
    c.enabled++
    println(c.enabled)  // true
}

It’s arguably a bit confusing (unless you think of Boolean as a cyclic type with two values) but it’s an option :grinning:


#5

For this particular case you could do:

myAnnoyinglyLongVariableOrExpression.apply { enabled = !enabled }

#6

That’s a very clever trick, and thinking of it as cyclic is (at least for me) actually quite intuitive. I like it - and will use it on my personal projects. Thanks!

Despite this, I think language support for this would be something to consider.


#7

I suspect that the best chance of something like this ever making it into the language in a more
recognizable form is for some way to be found to give infix functions an assignment form.

If that were the case, then you could use ‘xor’ to flip a Boolean variable’s value in the same way as you can use ‘^’ in Java. A possible syntax for that would be:

b xor= true

#8

This is the “cleverness” I’ve seen a lot in Scala. Using ++ and -- is counter intuitive and confusing. It is not worth it to save a bit of typing.

Why not wrapping the value to be inverted with a factory function which wraps it into an instance of a special class which then is grabbed by a Java agent to rewrite the bytecode? :wink:


#9

A generic solution would be adding support for inline classes to the language.


#10

This cannot be serious: Suggesting a complex language feature (inline classes) just because it is too cumbersome to type a = !a? Why replace code that is easy to type (especially with the code completion of the IDE), read and understand, with an entirely new concept?

Don’t you think that complex language features should be reserved for things that are really cumbersome to do without language support? For example: coroutines, multi-platform code, etc.


#11

Inline classes would have many more use cases. The use case outlined by the commenter before us is just one of many.

I’m not suggesting that inline classes should be implemented for this one use case. I am just telling that if inline classes are ever added as a language feature, than this use case would be solved implicitly.


#12

I did not mean to solely pick on your proposal. The premise that discussion of a language improvement for the negation of a boolean is valid, bothers me.

Suggesting workarounds, ugly hacks or advanced language features validates the question. And I strongly feel this question is silly, and the only proper response is: Just type the code. It is easy to do, and it will be easy to read. Anything else won’t add value.

Kotlin has excellent and concise support for negating a boolean (like most languages do). Sure, there probably are languages that can do it with less code. But what would be won with having a shorter Kotlin syntax, and at what cost? Do we really want the Kotlin team to spend time on a redundant language feature, just to save a few keystrokes in rare cases (I don’t know about you, but I guess I have to negate a boolean in 1 in 10,000 lines).


#13
import kotlin.reflect.*

fun main(args: Array<String>) {
    val a = A()
    a::x.flip()
    println(a.x)
}

class A {
    var x = false
}

fun KMutableProperty0<Boolean>.flip() = set(!get())

#14

Well that pretty much nails it for me at least.


#15

Nice. Can you explain the runtime implication of this solution? Is there reflection involved?


#16

I checked out his solution and it actually is not using Java reflection, a::x generates an instance of a little wrapper class that decompiled to Java looks like this:

final class FooKt$main$1 extends MutablePropertyReference0 {
   FooKt$main$1(A var1) {
      super(var1);
   }

   public String getName() {
      return "x";
   }

   public String getSignature() {
      return "getX()Z";
   }

   public KDeclarationContainer getOwner() {
      return Reflection.getOrCreateKotlinClass(A.class);
   }

   @Nullable
   public Object get() {
      return ((A)this.receiver).getX();
   }

   public void set(@Nullable Object value) {
      ((A)this.receiver).setX(((Boolean)value).booleanValue());
   }
}

So it doesn’t use reflection but is not something you would want to do a lot.


#17

BTW, there’s a great chance that advanced compilers like HotSpot inline get and set methods and, since FooKt$main$1 never escapes, eliminate its instantiation. So the only runtime implication is some wasted space in metaspace + jar (dex) file size. Note that such reasonings are merely speculation. The only proof is a benchmark.