加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 为什么不能优化隐式转换的这种情况?

发布时间:2020-12-16 18:51:02 所属栏目:安全 来源:网络整理
导读:为什么 Scala无法优化以下内容: 一个. 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
为什么 Scala无法优化以下内容:

一个.

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.你必须不必要地为这些额外的显式类创建名称),而且a的性能要差得多比b.

解决方法

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

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

但我不知道是否还有人写过这样的插件……

更新:

如果我编译这个文件:

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

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

并且为foo反编译代码,仍然涉及反射:

F:MyProgrammingraw>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:MyProgrammingraw>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:MyProgrammingraw>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

}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读