2010-10-06 41 views
6

Tại sao Scala không thể tối ưu hóa những điều sau:Tại sao không thể tối ưu hóa trường hợp chuyển đổi tiềm ẩn này?

a.

implicit def whatever[A](a: A) = new { ... } 

tới:

b.

class some$generated$name(a: A) { 
    ... 
} 
implicit def whatever[A](a: A) = new some$generated$name(a) 

?

Tại sao phải sử dụng tính năng nhập cấu trúc trong trường hợp này? Tôi muốn trình biên dịch Scala thực hiện tối ưu hóa này khi viết theo kiểu b chỉ là quá xấu (vì, 1. địa phương của logic bị mất, 2. bạn phải phát minh ra tên không cần thiết cho các lớp rõ ràng bổ sung này) và a kém hiệu quả hơn b.

+0

Đó không phải là "cấu trúc gõ." Đó là những đối tượng bao bọc ngầm cho các phương thức mở rộng. Kết cấu gõ là khi bạn xác định loại về phương pháp hoặc lĩnh vực họ có, chẳng hạn như 'loại Closeable = Bất kỳ {def close: Unit}' –

+1

@MJP: Tôi nhớ đã đọc nó ở đâu đó mã như trong ** a ** sử dụng các kiểu cấu trúc. – Jack

+2

@MJP: Có, và 'new {...}' được định nghĩa chính xác về phương thức và trường nào có ... –

Trả lời

3

tôi nghĩ rằng nó có thể, và điều này có thể được thực hiện với một plugin trình biên dịch, để tìm một cái gì đó giống như

@extension implicit def whatever[A](a: A) = new { ... } 

Nhưng tôi không biết nếu có ai đã viết như một plugin chưa ...

UPDATE:

Nếu tôi biên dịch tập tin này:

object Main { 
    implicit def option[A](a: A) = new { def id = a } 

    def foo(x: String) = x.id 
} 

và dịch ngược mã cho 012.380., phản ánh vẫn tham gia:

F:\MyProgramming\raw>javap -c Main$ 
Compiled from "Main.scala" 
public final class Main$ extends java.lang.Object implements scala.ScalaObject{ 
public static final Main$ MODULE$; 

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

public static java.lang.reflect.Method reflMethod$Method1(java.lang.Class); 
    Code: 
    0: getstatic  #20; //Field reflPoly$Cache1:Ljava/lang/ref/SoftReference; 
    3: invokevirtual #27; //Method java/lang/ref/SoftReference.get:()Ljava/lang/Object; 
    6: checkcast  #29; //class scala/runtime/MethodCache 
    9: ifnonnull  29 
    12: new  #23; //class java/lang/ref/SoftReference 
    15: dup 
    16: new  #31; //class scala/runtime/EmptyMethodCache 
    19: dup 
    20: invokespecial #32; //Method scala/runtime/EmptyMethodCache."<init>":()V 
    23: invokespecial #35; //Method java/lang/ref/SoftReference."<init>":(Ljava/lang/Object;)V 
    26: putstatic  #20; //Field reflPoly$Cache1:Ljava/lang/ref/SoftReference; 
    29: getstatic  #20; //Field reflPoly$Cache1:Ljava/lang/ref/SoftReference; 
    32: invokevirtual #27; //Method java/lang/ref/SoftReference.get:()Ljava/lang/Object; 
    35: checkcast  #29; //class scala/runtime/MethodCache 
    38: aload_0 
    39: invokevirtual #38; //Method scala/runtime/MethodCache.find:(Ljava/lang/Class;)Ljava/lang/r 
eflect/Method; 
    42: astore_1 
    43: aload_1 
    44: ifnull 49 
    47: aload_1 
    48: areturn 
    49: aload_0 
    50: ldc  #40; //String id 
    52: getstatic  #42; //Field reflParams$Cache1:[Ljava/lang/Class; 
    55: invokevirtual #48; //Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class 
;)Ljava/lang/reflect/Method; 
    58: astore_1 
    59: new  #23; //class java/lang/ref/SoftReference 
    62: dup 
    63: getstatic  #20; //Field reflPoly$Cache1:Ljava/lang/ref/SoftReference; 
    66: invokevirtual #27; //Method java/lang/ref/SoftReference.get:()Ljava/lang/Object; 
    69: checkcast  #29; //class scala/runtime/MethodCache 
    72: aload_0 
    73: aload_1 
    74: invokevirtual #52; //Method scala/runtime/MethodCache.add:(Ljava/lang/Class;Ljava/lang/ref 
lect/Method;)Lscala/runtime/MethodCache; 
    77: invokespecial #35; //Method java/lang/ref/SoftReference."<init>":(Ljava/lang/Object;)V 
    80: putstatic  #20; //Field reflPoly$Cache1:Ljava/lang/ref/SoftReference; 
    83: aload_1 
    84: areturn 

public java.lang.Object option(java.lang.Object); 
    Code: 
    0: new  #59; //class Main$$anon$1 
    3: dup 
    4: aload_1 
    5: invokespecial #60; //Method Main$$anon$1."<init>":(Ljava/lang/Object;)V 
    8: areturn 

public java.lang.String foo(java.lang.String); 
    Code: 
    0: aload_0 
    1: aload_1 
    2: invokevirtual #69; //Method option:(Ljava/lang/Object;)Ljava/lang/Object; 
    5: astore_2 
    6: aconst_null 
    7: astore_3 
    8: aload_2 
    9: invokevirtual #75; //Method java/lang/Object.getClass:()Ljava/lang/Class; 
    12: invokestatic #77; //Method reflMethod$Method1:(Ljava/lang/Class;)Ljava/lang/reflect/Metho 
d; 
    15: aload_2 
    16: iconst_0 
    17: anewarray  #71; //class java/lang/Object 
    20: invokevirtual #83; //Method java/lang/reflect/Method.invoke:(Ljava/lang/Object;[Ljava/lang 
/Object;)Ljava/lang/Object; 
    23: astore_3 
    24: aload_3 
    25: checkcast  #85; //class java/lang/String 
    28: checkcast  #85; //class java/lang/String 
    31: areturn 
    32: astore 4 
    34: aload 4 
    36: invokevirtual #91; //Method java/lang/reflect/InvocationTargetException.getCause:()Ljava/l 
ang/Throwable; 
    39: athrow 
    Exception table: 
    from to target type 
    8 24 32 Class java/lang/reflect/InvocationTargetException 


} 

Hãy so sánh với

object Main2 { 
    class Whatever[A](a: A) { def id = a } 

    implicit def option[A](a: A) = new Whatever(a) 

    def foo(x: String) = x.id 
} 

Và dịch ngược:

F:\MyProgramming\raw>javap -c Main2$ 
Compiled from "Main2.scala" 
public final class Main2$ extends java.lang.Object implements scala.ScalaObject{ 
public static final Main2$ MODULE$; 

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

public Main2$Whatever option(java.lang.Object); 
    Code: 
    0: new  #16; //class Main2$Whatever 
    3: dup 
    4: aload_1 
    5: invokespecial #20; //Method Main2$Whatever."<init>":(Ljava/lang/Object;)V 
    8: areturn 

public java.lang.String foo(java.lang.String); 
    Code: 
    0: aload_0 
    1: aload_1 
    2: invokevirtual #30; //Method option:(Ljava/lang/Object;)LMain2$Whatever; 
    5: invokevirtual #34; //Method Main2$Whatever.id:()Ljava/lang/Object; 
    8: checkcast  #36; //class java/lang/String 
    11: areturn 

} 

F:\MyProgramming\raw>javap -c Main2$Whatever 
Compiled from "Main2.scala" 
public class Main2$Whatever extends java.lang.Object implements scala.ScalaObject{ 
public java.lang.Object id(); 
    Code: 
    0: aload_0 
    1: getfield  #14; //Field a:Ljava/lang/Object; 
    4: areturn 

public Main2$Whatever(java.lang.Object); 
    Code: 
    0: aload_0 
    1: aload_1 
    2: putfield  #14; //Field a:Ljava/lang/Object; 
    5: aload_0 
    6: invokespecial #22; //Method java/lang/Object."<init>":()V 
    9: return 

} 
+0

tin xấu! bạn có thể bình luận về lý do tại sao mọi thứ theo cách này? –

+1

Đó là cách các kiểu cấu trúc hoạt động bình thường (xem http://infoscience.epfl.ch/record/138931/files/). Điều này có nghĩa là việc xây dựng này không phải là đặc biệt. –

2

Tôi đã đọc điều đó quá, và thường muốn hỏi câu hỏi này tương tự. Nhưng trên 2.8, tôi đang cố gắng nó ra:

object Main { 
    implicit def whatever[A](a: A) = new { def foo = "bar" } 
} 

Và khi tôi javap nó:

public final class Main$$anon$1 extends java.lang.Object{ 
    public java.lang.String foo(); 
    public Main$$anon$1(); 
} 

Hình như tin tức tốt, không có?

Cập nhật Bạn có thể theo dõi tối ưu hóa này sử dụng này trac item

+0

Thử cùng với '" ".foo'. Hoặc trực tiếp hơn, 'scala -Xprint: jvm'. – retronym

+1

Tin xấu: xem chỉnh sửa của tôi :( –

Các vấn đề liên quan