2013-07-14 18 views
5

Istnieje question z pytaniem o implementację lazy val s, jeśli są to zmienne klasy. Jak są realizowane lokalnych zmienne, takie wW jaki sposób są implementowane lokalne zmienne leniwy Scala?

def foo[A](a: => A) = { 
    lazy val x: A = a 
    // return something that uses x 
} 
+0

Logika jest taka sama, ale synchronizacja nie jest wymagana. –

+0

@RandallSchulz Ale co jeśli 'x' wymyka się jego zakresowi, jak w [tutaj] (https://github.com/scalaz/scalaz/blob/59bdfecdae88f8e166f8d39cd08879ed87f3db17/core/src/main/scala/scalaz/Name.scala#L39)? Dostęp do niego można uzyskać dzięki wielu wątkom. –

+0

Hmmm ... Tak! W takim przypadku wymagana byłaby wyraźna synchronizacja. –

Odpowiedz

3

To nieco mniej wydajny w użyciu leniwe Vals w metodzie. Powodem jest to, że nie można faktycznie zagnieżdżać funkcji, więc leniwe bity, które nominalnie są przydzielane na stosie, rzeczywiście muszą przejść na ster. Musisz więc stworzyć co najmniej jeden dodatkowy obiekt i okazuje się, że Scala faktycznie tworzy dwa.

class Baz{ 
    def baz(i: => Int, b: Boolean) = { 
    lazy val j = i 
    if (b) j else 0 
    } 
} 

zamienia się między innymi

public int baz(scala.Function0, boolean); 
    Code: 
    0: new #12; //class scala/runtime/IntRef 
    3: dup 
    4: iconst_0 
    5: invokespecial #16; //Method scala/runtime/IntRef."<init>":(I)V 
    8: astore_3 
    9: new #18; //class scala/runtime/VolatileByteRef 
    12: dup 
    13: iconst_0 
    14: invokespecial #21; //Method scala/runtime/VolatileByteRef."<init>":(B)V 
    17: astore 4 
    19: iload_2 
    20: ifeq 34 
    23: aload_0 
    24: aload_1 
    25: aload_3 
    26: aload 4 
    28: invokespecial #25; //Method j$1:(Lscala/Function0;Lscala/runtime/IntRef; 
               Lscala/runtime/VolatileByteRef;)I 
    31: goto 35 
    34: iconst_0 
    35: ireturn 

Zobacz tworzenie IntRef i VolatileByteRef? Są na miejscu tego, co normalnie byłoby po prostu prywatnymi varami, aby poradzić sobie z leniwym valem. A teraz j$1, metoda accessor utworzona do obsługi pobierania i/lub tworzenia leniwego val, musi przyjąć te dwie nowo utworzone klasy jako parametry (oprócz funkcji nazwy).

Tak więc, podczas gdy podstawowa mechanika jest taka sama, szczegóły implementacji są inne i mniej wydajne, niż gdybyś miał już inną klasę, w której można trzymać znaki.

Powiązane problemy