2012-12-29 14 views
6

Kiedy używam val w for-rozumienia, pojawia się ostrzeżenie:Jakie są zasady wyznaczania zasięgu Vals w Scala dla-listowe

ostrzeżenie: val słowo kluczowe dla rozumienia jest przestarzała

pomimo produkcji w dodatku do składni specyfikacji.

Sugeruje to, że kiedy robię coś takiego

for (x <- xs; a = x) 

nie jestem wprowadzenie zmiennej, jak gdybym coś takiego

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

gdzie, jak zwykle, początkami karczkiem nowy zakres, w którym mogę wprowadzić nowy val, a nawet nowy domyślny.

Co tak naprawdę robię z tym a?

Czy zajmuję miejsce na stos? Sterta? Jakiś inny rodzaj pseudonimu?

Odpowiedz

7

Podobnie jak zwykła definicja rzecz po lewej stronie znaku równości jest po prostu wzorcem.

Produkcja modułu Enumerator w specyfikacji składni pokazuje, że klauzula w wyrażeniu for-expr może być generatorem (a <- b), ochroną if cond lub val def a = b.

Części, które mogą być arbitralne, to: b (podane na prawo od <- i =) oraz stan.

Responder.exec korzysta z warunkowego wykonania niepożądanego kodu, a następnie ocenia w sposób trywialny na true.

Oznacza to, że można zrobić dowolne efekty uboczne od warunkowa:

// 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) 

Podobnie Val def desugars następująco:

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) } 

Czekaj, naprawdę?

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

Musisz niedawnym repl, aby to zrobić:

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  

widzę dwie inwokacje na mapie, dla ekspresji pośredniej i wydajności.

Po dokładnej inspekcji, pierwsza anonfun nie jest Int => Int (tj., a+1), ale Int => (Int,Int).

Tak więc wprowadzony przez nas val jest właśnie przekazywany jako część krotki.

Powiązane problemy