Switch / case very interesting in Swift - What other languages support this?

12

The Swift language has a very interesting and intuitive way to work with switch-case breaks, with partial-matching, pattern-matching, etc. techniques, see these examples:

let age = 33

switch(age){
case let x where x >= 0 && x <= 2:
    print("Infant")
case let x where x >= 3 && x <= 12:
    print("Child")
case let x where x >= 13 && x <= 19:
    print("Teenager")
case let x where x >= 20 && x <= 39:
    print("Adult")
case let x where x >= 40 && x <= 60:
    print("Middle aged")
case let x where x >= 61:
    print("Elderly")
default:
    print("Invalid")
}

Another very interesting example:

let string = "Dog"
switch(string){
    case "Cat","Dog":
        print("Domestic animal")
    case "Lion","Leopard","Pantera":
        print("Never touch me")
    default:
        print("By the way, don't touch... :-)")
} 

Are there other languages that enable these features? I've never been able to make a switch case in Java. I've also never been curious to know if it would work :-) I've always used a different logic approach.

Editing: Adding an incredible example of "partial matching":

let coordinates: (x: Int, y: Int, z: Int) = (3, 0, 0)
switch (coordinates) {
case (0, 0, 0): // 1
    print("Origin")
case (_, 0, 0): // 2
    print("On the x-axis.")
case (0, _, 0): // 3
    print("On the y-axis.")
case (0, 0, _): // 4
    print("On the z-axis.")
default:        // 5
    print("Somewhere in space")
}

In the above case, the program will parse by default, since it is a point in X and the rest of the axes in zero. "On the X axis". In Java I would not use a switch case and simply a getX of the object not interested the rest, everything with else if, would write less and would have the same result. But I found it different how Swift had that freedom.

It seems to me that VB also has a similar technique.

Hugs to all.

    
asked by anonymous 30.06.2016 / 02:44

4 answers

14

All languages that allow pattern matching : P

I have my doubts there if this question is helpful.

I do not know if I'm taking the risk of saying that all functional languages support this mechanism. Some in one way, some in another, some more limited. For good or ill, none is used intensely in the market. Some Wikipedia examples .

Most modern, even non-functional languages are supporting the engine because it is useful. Some languages are evolving to support, this is the case with C # . Which will do, along with Swift, the only languages with expressive use (Swift still needs to eat beans, but arrives there quickly) that support this for some time. As far as I know, Java, C / C ++ / Obj C, PHP, Python, Perl, Ruby, JS, Lua, Delphi, VB (. they are not planning this anytime soon. But you can change, stay tuned.

Rust is an aspiring language it has.

In any language it is possible to simulate this, but it will not be very convenient and may affect performance.

    
30.06.2016 / 03:12
8

In Python there was an intense discussion about this in forums where the future of language is discussed at the beginning of the year - but the inclusion of a specialized command equivalent to switch/case has been declined by the (again) community.

This is because it is understood that if/elif/else of Python serves everything that is possible to do with a switch / case and even more expressiveness (since the expressions can not only be matching, but include other tests as well) . The only "cost" is to have to repeat the tested variable on every occurrence of elif - but this is also accompanied by greater readability.

As for matching - it is not part of the language syntax, it can be embedded in any third-party package and used as a normal function (just like regular expressions in Python). Again, the readability wins. If a third matching package appears that is actually a "de facto standard" it can be incorporated into the default language library. (Intervals have been supported in Python for a long time)

    
30.06.2016 / 15:47
6

Complementing this as a curiosity.

Comparing with the examples of the question, it shows how it would look like in a language like PHP. Note that practically the same syntax applies to JavaScript, ActionScript, and many others with similar syntax.

I will only put one condition for each one to reduce the codes

Example 1

SWIFT

let age = 33

switch(age){
case let x where x >= 0 && x <= 2:
    print("Infant")
default:
    print("Invalid")
}

PHP

$age = 33;
switch (true) {
    case ($age >= 0 && $age <= 2):
        echo 'infant';
        break;
    default:
        echo 'invalid';
        break;
}

JavaScript

var age = 33;
switch (true) {
    case (age >= 0 && age <= 2):
        console.log('infant');
        break;
    default:
        console.log('invalid');
        break;
}

Example 2

SWIFT

let string = "Dog"
switch(string){
    case "Cat","Dog":
        print("Domestic animal")
    case "Lion","Leopard","Pantera":
        print("Never touch me")
    default:
        print("By the way, don't touch... :-)")
} 

PHP

It does not change at all. It follows the same logic as the example:

$str = 'Dog';
switch (true) {
    case stripos('Cat, Dog', $str):
        echo 'Domestic animal';
        break;
    default:
        echo 'By the way, don't touch... :-)';
        break;
}

JavaScript

Same as PHP except for the stripos () function. Just swap for equivalent function in JS.

Example 3

SWIFT

let coordinates: (x: Int, y: Int, z: Int) = (3, 0, 0)
switch (coordinates) {
case (0, 0, 0): // 1
.......

Finally, follow the same logic as the other two examples above.

In this case, in PHP, the most obvious is to use array and compare values.

$arr = array(0, 0 , 0);
switch (true) {
    case (funcao_para_comparar($arr, array(0, 0, 0))):
    ...... faz as coisas que tem que fazer ,etc..


function funcao_para_comparar($arr1, $arr2) {
  ... faz as firulas aqui e pá.
}

The important thing is that the condition returns the expected value in the switch () parameter, which in the examples above is boolean true .

Because the codes are repetitive, I find it unnecessary to write more of them.

    
01.07.2016 / 06:01
5
  

Warning: This answer is an add-on.

Supporting a specific kind of syntax - such as this one - are almost always considered low priority for a number of languages for a number of reasons, including:

  • Little benefit for the level of complexity to implement and maintain - thinking about compatibility with future versions and previous releases.
  • More advanced features that visibly impact performance tend to be misused by many users, so some languages prefer to stick to what is simpler.
  • There are other better ways to do the same thing.

Examples in Java

Age range

Given an enum:

enum LifeStage {
    Infant(2), Child(12), Teenager(19), Adult(39), MiddleAged(60), Elderly(Integer.MAX_VALUE);
    private final int limite;
    LifeStage(int limite) {
        this.limite = limite;
    }
    public boolean match(int age) {
        return age <= limite;
    }
}

The code to find the description for age falls to a line using functional programming:

int age = 33;
Optional<LifeStage> stage = Arrays.stream(LifeStage.values()).filter(v -> v.match(age)).findFirst();
System.out.println(stage.get());

In% with original, it is unnecessary to check the lower range if age is always switch .

However, even if it were necessary to execute a complex logic of any nature, it would suffice to change the >= 0 method of the above enum. The big advantage is that the "search" method would not change as it is decoupled from the implementation.

Multiple values

Comparing all values is always inefficient. Java has deferred match to strings for this reason. It is much simpler and more efficient to use a previously prepared map, for example:

Map<String, String> animalCategories = new HashMap<>();
String da = "Domestic Animal";
animalCategories.put("Cat", da);
animalCategories.put("Dog", da);
String ntm = "Never touch me";
animalCategories.put("Lion", ntm);
animalCategories.put("Leopard", ntm);
animalCategories.put("Pantera", ntm);

And then just consult:

String dog = "Dog";
String category = animalCategories.get(dog);
System.out.println(category);

Coordinates

In Java you need a class and if it is immutable, better yet, just define the "description" of the type of coordinate in the constructor, and you can use a composition of ternaries for this:

class Coord {
    private final int x, y, z;
    private final String desc;

    Coord(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
        desc = x == 0 && y == 0 & z ==0 ? "Origin" :
                x != 0 && y == 0 & z ==0 ? "On the x-axis." :
                x == 0 && y != 0 & z ==0 ? "On the y-axis." :
                x == 0 && y == 0 & z !=0 ? "On the z-axis" :
                "Somewhere in space";
    }
    public String getDesc() {
        return desc;
    }
}

And to use:

Coord c = new Coord(3, 0, 0);
System.out.println(c.desc);

Considerations

I'm not saying that languages like Java are perfect. There are, indeed, many improvements missing in her and in other languages.

On the other hand, what has to be clear in "language warfare" is that having the largest set of functionalities or the greatest variety of syntactic constructs is not a relevant factor in their absolute value. Some authors argue that a new feature is only worthwhile if the benefit gained from its use is greater than the overhead implies by its use.

    
01.07.2016 / 05:34