How quickly a pattern is matched in Scala

I am new to Scala. When I study it while reading Scala code written by others, one of the most distinctive features that I find in Scala code, which differs from other languages, is its comparison with the sample.

At the same time, I feel the convenience and expressiveness that it brings; I cannot but curiously evaluate the potential cost of working behind it - generally speaking, how fast match?

Firstly, without "advanced" functions, such as mapping parameters of constructors, matchin Scala, IMO, is an analogue switch-casein other languages. For instance,

color match {
  0 => println "color is red!"
  1 => println "color is green!"
  2 => println "color is blue!"
}

As a newbie, I want to know if the code above is just as fast as the equivalent code in an expression if-else?

Secondly, now we return these "advanced" functions, for example:

expr match {
  Animal(name) => ...
  Animal(name, age) => ...
  Animal(_, _, id) => ...
}

Regarding the above code or other matching features (matching lists, matching pairs, etc.), I wonder how this bizarre use of Scala is implemented? And most importantly, how quickly can I expect this code to be? (Tell me, are they still as fast as matchin the first case? Or maybe a little slower? Or very slow due to the use of some technologies, such as reflection?)

Thanks in advance!

+4
source share
1 answer

The first fragment translates to bytecode TableSwitch(or LookupSwitch) and works as fast as the Java / case switch:

scala> def foo(i: Int) = i match {
     | case 1 => 2
     | case 2 => 10
     | case 3 => 42
     | case _ => 777
     | }
foo: (i: Int)Int

scala> :javap -c foo
Compiled from "<console>"
public class  {
  public static final  MODULE$;

  public static {};
    Code:
       0: new           #2                  // class
       3: invokespecial #12                 // Method "<init>":()V
       6: return

  public int foo(int);
    Code:
       0: iload_1
       1: istore_2
       2: iload_2
       3: tableswitch   { // 1 to 3
                     1: 44
                     2: 39
                     3: 34
               default: 28
          }
      28: sipush        777
      31: goto          45
      34: bipush        42
      36: goto          45
      39: bipush        10
      41: goto          45
      44: iconst_2
      45: ireturn

  public ();
    Code:
       0: aload_0
       1: invokespecial #18                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: putstatic     #20                 // Field MODULE$:L;
       8: return

unapply/isInstanceOf/null checks () , TableSwitch. ( , - ), isInstanceOf ( ):

scala> case class Foo(s: String, i: Int)
defined class Foo

scala> def bar(foo: Foo) = foo match {
     | case Foo("test", _) => 1
     | case Foo(_, 42) => 2
     | case _ => 3
     | }
bar: (foo: Foo)Int

scala> :javap -c bar
Compiled from "<console>"
public class  {
  public static final  MODULE$;

  public static {};
    Code:
       0: new           #2                  // class
       3: invokespecial #12                 // Method "<init>":()V
       6: return

  public int bar(Foo);
    Code:
       0: aload_1
       1: astore_2
       2: aload_2
       3: ifnull        26
       6: aload_2
       7: invokevirtual #20                 // Method Foo.s:()Ljava/lang/String;
      10: astore_3
      11: ldc           #22                 // String test
      13: aload_3
      14: invokevirtual #26                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
      17: ifeq          26
      20: iconst_1
      21: istore        4
      23: goto          52
      26: aload_2
      27: ifnull        49
      30: aload_2
      31: invokevirtual #30                 // Method Foo.i:()I
      34: istore        5
      36: bipush        42
      38: iload         5
      40: if_icmpne     49
      43: iconst_2
      44: istore        4
      46: goto          52
      49: iconst_3
      50: istore        4
      52: iload         4
      54: ireturn

  public ();
    Code:
       0: aload_0
       1: invokespecial #34                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: putstatic     #36                 // Field MODULE$:L;
       8: return
}
+7

Source: https://habr.com/ru/post/1654574/


All Articles