2

In GoLang you can have a switch without an expression, where the cases replace a series of cascading ifs.

t := time.Now()
switch {
case t.Hour() < 12:
    fmt.Println("It's before noon")
default:
    fmt.Println("It's after noon")
}

In Java 19 I can simulate this with this kind of hack by using switch pattern matching with "guarded pattern when" and when the main expression is always true and the guarded pattern does the real work. ( Or in Java 17 but using && instead of when)

int num=5;
switch (System.out) {
    case Object o when num>100 -> System.out.println("Big");
    case Object o when num>50 -> System.out.println("Med");
    default -> {System.out.println("Small");}
}

Obviously these simple cases can be written without a switch, but when you have a long series of if-else-if=else, not necessarily on the same variable, this kind of structure can be more concise.

Anyone know a nicer way to do this?

Gonen I
  • 5,576
  • 1
  • 29
  • 60
  • 3
    Sorry if this is a stupid question, but: what's the advantage of this notation over using if/else if? – ruakh Nov 17 '22 at 08:33
  • 1
    it is just more concise sometimes and looks cleaner. No need for cascading ifs that keep sliding to the right. – Gonen I Nov 17 '22 at 08:34
  • 2
    @GonenI `if` ... `then` ... `else if` ... is not sliding to the right – Christoph S. Nov 17 '22 at 08:39
  • 1
    As Gonen said, there is no "sliding to the right" of ifs (I 'll just assume you mean indentation) unless you nest them, and if you do so, the same will occur with switch-case – Stultuske Nov 17 '22 at 08:42
  • For 2 "cases" an if-statement is normally enough... But just for the sake of @GonenI argument, when there is 5 "cases" an if-statement can get messy. – Reg Nov 17 '22 at 08:45
  • 2
    `System.out.println(num > 100? "Big": num > 50? "Med": "Small");` or, when it really has to be a `switch`, you can use `System.out.println(switch((num-1)/50) { default -> "Big"; case 1 -> "Med"; case 0 -> "Small"; });` – Holger Nov 17 '22 at 08:56
  • 1
    The closest to your idea would be the (modified) example taken from [JEP 427](https://openjdk.org/jeps/427) (right above section 2): `Integer num = 5; switch(num) { case Integer i when i > 100 -> ...; case Integer i when i > 50 -> ...; default -> ...;}`. – Thomas Nov 17 '22 at 09:00
  • 2
    The first example could be written as `System.out.println("It's " + (LocalTime.now().get(ChronoField.AMPM_OF_DAY) == 0? "before": "after") + " noon");` There is no elegance in using a `switch` with redundant code in each `case` – Holger Nov 17 '22 at 09:02

1 Answers1

2

There a few principles that I can think of that can guide decisions for situations like this:

  1. Avoid over-engineering
  2. The principle of least-surprise
  3. Use the right tool for the job

The switch statement is used for executing different code paths based on possible values of a particular variable. The when extension was invented to add some flexibility and terseness to this mechanism, but the original purpose of the mechanism is still there: to switch on possible values of a particular variable.

The very concept of a "switch" is based on the idea of more than one outcome which is controlled by something; in the case of the switch statement, that something is the switch expression. If there is no switch expression, then it is not a switch, it is a collection of mutually exclusive rules.

Another idea behind the invention of the switch statement was the possibility of optimization. The original implementations of switch statements used highly efficient lookup tables, that's why they could only operate on int. Modern switch statements work on more complex values, but when there is a single controlling switch expression there is still some possibility of optimization. No such thing happens when there is no switch expression.

When I see a switch statement, I expect to see various different things done based on different values of a particular variable; I do not expect to see just about anything being done in there. If I study the code and I notice that my expectation is not met, I will be mighty surprised. Disappointed even.

So, the nicer way of doing this is to go back to the good old, familiar, tried-and-true, cascaded if-else statement.


The fact that golang allows the creation of meaningless switch statements means absolutely nothing to me. Many languages make useless choices. Many languages do not even have any particular reason of existence. Many people consider the "idiomatic" way of doing things in a particular language to be a goal in and of itself, while it is not. If you feel tempted to take an idiomatic feature of your favorite language and apply it in other languages, first ask yourself whether the feature had any merit even in the original language. Often, it does not.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
  • 2
    Thanks. I agree with the principle of least surprise. I wouldn't write code like this which emulates a structure that isn't truly implemented in the language. I mostly wanted to check if I hadn't missed something that has become available in recent versions. – Gonen I Nov 17 '22 at 12:10
  • "The principle of least-surprise" - so true – Christoph S. Nov 17 '22 at 16:49