6

我知道这些方法可能被认为是“等效的”或“同义词”,尽管不是“相同的”,根据诸如调用 collection.size 或 collection.length 的最佳 Scala 约定Scala 缓冲区:大小或长度?.

但这是否意味着它们是相同的?

不要向我提供意见或一成不变的轻率概念。告诉我什么时候它们实际上不一样。

用硬科学支持你的主张!

字节码就足够了。我对特定于 JIT 的优化不太感兴趣。

我对世界的当前状态特别感兴趣,即最近里程碑中的 Scala 2.11。

4

1 回答 1

8

在 2.11 中,String 和 Array 仍然被包装成大小。

你应该训练你的手指打字s.lengtharr.length

这并不难,因为字符串和数组都有长度。

从 Java 来到 Scala 的人通常会决定是使用方法java.lang.String还是方便的扩充。由于在我们被要求用休息室的甜甜圈补充它之前,我们有一个有限的“决策预算” ,因此值得提前做出一些这样的决定作为政策问题。

如果一个人在午餐或甜甜圈上没有什么好讨论的:

22: invokevirtual #41                 // Method scala/Predef$.augmentString:(Ljava/lang/String;)Ljava/lang/String;
25: invokespecial #44                 // Method scala/collection/immutable/StringOps."<init>":(Ljava/lang/String;)V
28: invokevirtual #47                 // Method scala/collection/immutable/StringOps.size:()I


18: invokevirtual #39                 // Method scala/Predef$.intArrayOps:([I)Lscala/collection/mutable/ArrayOps;
21: invokeinterface #44,  1           // InterfaceMethod scala/collection/mutable/ArrayOps.size:()I

等等,等等,使用 -optimise 你可能会丢失augmentString。

GenSeqLike引入length并指定它“产生相同的结果”作为size. SeqLike以这种方式实现它。

实际上,通过对 a 的扩充来String获得一个方法,特别是. 这需要包装。事实上,预测哪些调用需要包装或分派到扩展方法并不容易。sizeSeqLikeStringLike

例如,length以不需要包装的方式定义。那是因为StringOps它是一个值类。事实上,它编译为String.length.

然而,定义为模拟数组 apply的调用的applyon 方法虽然以相同的方式定义,但调用了扩展方法。StringOpscharAt

(当然,在 JIT 编译之后,一些操作码和分配可能意义不大。)

scala> val s = "hello"
s: String = hello

scala> val n = s.length ; val i = s.size ; val c = s(4) ; s.slice(0,4)
n: Int = 5
i: Int = 5
c: Char = o
res0: String = hell

scala> :javap -prv -
  public $line4.$read$$iw$$iw$();
    flags: ACC_PUBLIC
    Code:
      stack=5, locals=7, args_size=1
         0: aload_0       
         1: invokespecial #32                 // Method java/lang/Object."<init>":()V
         4: aload_0       
         5: putstatic     #34                 // Field MODULE$:L$line4/$read$$iw$$iw$;
         8: aload_0       
         9: getstatic     #39                 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
        12: invokevirtual #42                 // Method $line3/$read$$iw$$iw$.s:()Ljava/lang/String;

length

        15: invokevirtual #47                 // Method java/lang/String.length:()I
        18: putfield      #22                 // Field n:I
        21: aload_0     

new StringOps, 或StringOops:

        22: new           #49                 // class scala/collection/immutable/StringOps
        25: dup           
        26: getstatic     #54                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
        29: getstatic     #39                 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
        32: invokevirtual #42                 // Method $line3/$read$$iw$$iw$.s:()Ljava/lang/String;
        35: astore_2      
        36: astore_1      
        37: aload_2       

StringOps.size

        38: invokespecial #57                 // Method scala/collection/immutable/StringOps."<init>":(Ljava/lang/String;)V
        41: invokevirtual #60                 // Method scala/collection/immutable/StringOps.size:()I
        44: putfield      #25                 // Field i:I
        47: aload_0       
        48: getstatic     #65                 // Field scala/collection/immutable/StringOps$.MODULE$:Lscala/collection/immutable/StringOps$;
        51: getstatic     #54                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
        54: getstatic     #39                 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
        57: invokevirtual #42                 // Method $line3/$read$$iw$$iw$.s:()Ljava/lang/String;
        60: astore        4
        62: astore_3      
        63: aload         4
        65: iconst_4      

apply扩展方法:

        66: invokevirtual #69                 // Method scala/collection/immutable/StringOps$.apply$extension:(Ljava/lang/String;I)C
        69: putfield      #28                 // Field c:C
        72: aload_0       
        73: getstatic     #65                 // Field scala/collection/immutable/StringOps$.MODULE$:Lscala/collection/immutable/StringOps$;
        76: getstatic     #54                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
        79: getstatic     #39                 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
        82: invokevirtual #42                 // Method $line3/$read$$iw$$iw$.s:()Ljava/lang/String;
        85: astore        6
        87: astore        5
        89: aload         6
        91: iconst_0      
        92: iconst_4      

slice

        93: invokevirtual #73                 // Method scala/collection/immutable/StringOps$.slice$extension:(Ljava/lang/String;II)Ljava/lang/String;
        96: putfield      #31                 // Field res0:Ljava/lang/String;
        99: return   
于 2013-11-07T01:50:15.183 回答