2010-10-06 75 views
6

为什么Scala不能优化以下内容:为什么不能优化隐式转换的这种情况?

a。

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

到:

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

为什么在这种情况下必须使用结构打字?我想Scala编译器执行此优化,在写作风格b是太丑陋(因为,1,逻辑的地方丢失,2.你必须不必要的发明名称为这些额外的明确的类),并一个性能远低于b

+0

也就是说不会跟踪优化“结构打字。”这些是扩展方法的隐式包装对象。结构类型是当你根据它们具有的方法或字段来定义类型时,例如'type Closeable = Any {def close:Unit}' – 2010-10-06 02:38:08

+1

@MJP:我记得在** a **使用结构类型。 – Jack 2010-10-06 02:43:28

+2

@MJP:是的,'new {...}'是根据它有什么方法和字段来精确定义的... – 2010-10-06 06:16:15

回答

3

我认为这可能,而这可以通过编译器插件来完成,看起来像

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

但我不知道是否有人写然而,这样一个插件...

UPDATE:

如果我编译该文件:

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

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

和反编译代码,反思仍在参与:

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 


} 

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 
} 

和反编译比较:

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

坏消息!你能评论为什么事情是这样吗? – 2010-10-16 14:06:51

+1

这就是结构类型通常的工作原理(参见http://infoscience.epfl.ch/record/138931/files/)。这只是意味着这种结构不是特殊的。 – 2010-10-16 18:01:06

2

我读到过了,经常要问同样的问题。但在2.8,我想出来:

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

当我的javap它:

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

看起来是个好消息,不是吗?

更新您可以使用此trac item

+0

尝试使用'“”.foo'。或者更直接地说,'scala -Xprint:jvm'。 – retronym 2010-10-16 13:17:45

+1

坏消息:看我编辑:( – 2010-10-16 13:25:14

相关问题