2016-09-14 1 views
4

저는 스칼라를 처음 접했습니다. 스칼라 코드에서 다른 사람들이 쓴 스칼라 코드를 읽음으로써 스칼라 코드를 배울 때 스칼라 코드에서 다른 언어와 다른 점은 패턴 매칭이다.스칼라에서 패턴 매칭이 얼마나 빠릅니다.

동시에 내가 제공하는 편리함과 표현력을 느낄 수 있으며 잠재적 인 성능 비용에 궁금증을 느끼는 것을 도울 수 없습니다. 일반적으로 말해서 얼마나 빨리 match입니까?

먼저, 스칼라에서 IMO 인 match은 다른 언어로 switch-case에 해당합니다. 위의 코드는 if-else 문에 해당하는 코드로 정확하게 빠른 경우 초보자로서 예,

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

, 나는 알고 싶어? 지금 사람들을 복용 둘째

, "고급"예를 들어, 다시 기능 :

이 경기의 다른 기능 (목록 일치, 쌍 일치 등) 또는 위의 코드에 관해서는
expr match { 
    Animal(name) => ... 
    Animal(name, age) => ... 
    Animal(_, _, id) => ... 
} 

, 내가 궁금합니다 스칼라가이 멋진 사용법을 어떻게 구현 했습니까? 그리고 가장 중요한 것은이 코드가 얼마나 빠를 것이라고 기대할 수 있습니까? (말하자면, 그들은 여전히 ​​첫 번째 경우 match만큼 빠르지 않습니까? 아니면 조금 느린가, 아니면 리플렉션과 같은 일부 기술을 사용하여 매우 느려지는 것입니까?)

미리 감사드립니다.

+1

은 상황에 따라 달라집니다 : isInstanceOf (NO 반사 또는 유사한 물건)을 통해 수동 검사 등의 성능을 (컴파일러가 뭔가를 최적화 할 수있는 경우, 또는 더 나은) 그러나 같은이 상수를 포함하는 제한된 경우에,이 같이있을거야 자바 스위치. 내장 case 클래스 패턴에 패턴 매칭이 필요한 경우 인스턴스 체크와 필드 검색을 수행합니다. 일반적인 경우,'unapply' 메소드 전체가 호출됩니다 (예, 느리다). – Alec

답변

7

첫 번째 조각은 바이트 코드의 TableSwitch (또는 LookupSwitch)로 번역 및 Java의 스위치/사례로 빨리이다 :

두 번째 잘린는 unapply/isInstanceOf/null checks 통화의 무리로 번역, 느린 tableswitch을보다 (명백하게)이다

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 
.

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 
} 
+0

자신 만의 특별한 치료법을 얻기 때문에 case 생성자 패턴과 일치하는 패턴을보기에는별로 좋지 않습니다. 만약 당신이 자신의'unapply' 패턴을 작성한다면, 나는'javap' 덤프가 훨씬 더 흉측해질 것이라고 생각합니다. – Alec

+1

글쎄, 그리 못 생겼어. 두 번째 바이트 코드 스 니펫 (isInstanceOf', null 검사)과 유사하지만 가능한 최적화가 없습니다. 스칼라 컴파일러는 사례 클래스의 메커니즘이 고정되어 있지만 추출기의 unapply 또는 unapplySeq 메서드는 거의 모든 것을 수행 할 수 있기 때문에 추출기의 패턴보다 케이스 클래스보다 훨씬 좋은 패턴을 최적화 할 수 있습니다. – dveim

+0

최소한 Option [(..)] 옵션 튜플 객체 중 일부는 최적화되지 않은 상태로 유지 될 것이라고 추측했습니다 (instanceof 및 null check 만 필요한 생성자 패턴과 달리 패턴을 반박 할 수 있으므로). 그것은 비교적 비효율적 인 것처럼 보인다. – Alec

관련 문제