2012-12-29 6 views
6

Wenn ich ein val in einem für Verständnis verwenden, erhalte ich die Warnung:Was die Scoping-Regeln für vals in Scala für-Comprehensions sind

Warnung: val Schlüsselwort in für das Verständnis ist veraltet

trotz der Produktion in der Syntax Anhang der Spezifikation.

Dies deutet darauf hin, dass, wenn ich so etwas wie

for (x <- xs; a = x) 

Ich bin nicht wirklich eine Variable, wie wenn ich etwas tun wie

for (x <- xs) yield { implicit val a = x; /* more */ } 

wo, wie üblich, die Klammer beginnt die Einführung ein neuer Bereich, in dem ich ein neues val einführen kann, oder sogar ein neues implizit.

Was mache ich wirklich mit dieser a?

Benötige ich Stapelspeicher? Haufen? Eine andere Art von Alias?

Antwort

7

Wie eine gewöhnliche val pat = expr Definition ist das Ding auf der linken Seite des Gleichheitszeichens nur ein Muster.

Die Enumerator Produktion in der Syntax-Spezifikation zeigt, dass die Klausel in einem for-ausdr (a <- b) ein Generator sein kann, zu schützen if cond oder val def a = b.

Die Teile, die beliebige Ausdrücke sein können, sind b (wie rechts von <- und = angegeben) und die Bedingung.

Responder.exec nutzt die Bedingung, um beliebigen Code auszuführen, während trivial zu true ausgewertet wird.

Das bedeutet, dass Sie beliebige Nebenwirkungen von einem bedingten tun könnte:

// yucky, yet instructive 
scala> val xs = List(1,2,3) 
scala> def bar(implicit i: Int) = Some(i+1) 
scala> implicit var imp: Int = 0 
scala> for { a<-xs; if { imp=a; true }; b<-bar } yield b 
res6: List[Int] = List(2, 3, 4) 

Ebenso die val def desugars wie folgt:

tmp <- xs 
a = f(tmp) // some arbitrary function of tmp 
// amounts to 
(tmp, a) <- for ([email protected] <- xs) yield { val [email protected]=f(tmp); (x, x0) } 

Warten, wirklich?

scala> def f(vs: List[Int]) = for (a <- vs; b = a+1) yield b 
f: (vs: List[Int])List[Int] 

Sie erhalten eine letzte repl müssen dies tun:

scala> :javap f 
[snip] 
    public scala.collection.immutable.List<java.lang.Object> f(scala.collection.immutable.List<java.lang.Object>); 
    flags: ACC_PUBLIC 

    Code: 
     stack=3, locals=2, args_size=2 
     0: aload_1  
     1: new   #16     // class $anonfun$f$1 
     4: dup   
     5: invokespecial #17     // Method $anonfun$f$1."<init>":()V 
     8: getstatic  #22     // Field scala/collection/immutable/List$.MODULE$:Lscala/collection/immutable/List$; 
     11: invokevirtual #26     // Method scala/collection/immutable/List$.canBuildFrom:()Lscala/collection/generic/CanBuildFrom; 
     14: invokeinterface #32, 3   // InterfaceMethod scala/collection/TraversableLike.map:(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object; 
     19: checkcast  #28     // class scala/collection/TraversableLike 
     22: new   #34     // class $anonfun$f$2 
     25: dup   
     26: invokespecial #35     // Method $anonfun$f$2."<init>":()V 
     29: getstatic  #22     // Field scala/collection/immutable/List$.MODULE$:Lscala/collection/immutable/List$; 
     32: invokevirtual #26     // Method scala/collection/immutable/List$.canBuildFrom:()Lscala/collection/generic/CanBuildFrom; 
     35: invokeinterface #32, 3   // InterfaceMethod scala/collection/TraversableLike.map:(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object; 
     40: checkcast  #37     // class scala/collection/immutable/List 
     43: areturn  

Ich sehe zwei Anrufungen der Karte, für die Zwischen Expression und für die Ausbeute.

Bei einer weiteren Untersuchung ist die erste anonfun keine Int => Int (d.h. a+1), sondern eine Int => (Int,Int).

Also wird das Val, das wir eingeführt haben, nur als Teil eines Tupels weitergegeben.

Verwandte Themen