2012-12-29 26 views
6

là gì Khi tôi sử dụng một val trong một cho-hiểu, tôi nhận được cảnh báo:các quy tắc Phạm vi cho Vals tại Scala cho-comprehensions

cảnh báo: từ khóa val trong cho sự hiểu biết bị phản

bất chấp việc sản xuất trong phụ lục cú pháp của thông số kỹ thuật.

Điều này cho thấy rằng khi tôi làm điều gì đó như

for (x <- xs; a = x) 

Tôi không thực sự giới thiệu một biến, chẳng hạn như nếu tôi làm điều gì đó như

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

ở đâu, như thường lệ, nẹp bắt đầu một phạm vi mới, nơi tôi có thể giới thiệu một val mới, hoặc thậm chí là một tiềm ẩn mới.

Tôi thực sự đang làm gì với điều đó a?

Tôi có đang sử dụng không gian ngăn xếp không? Heap? Một số loại bí danh khác?

Trả lời

7

Giống như định nghĩa thông thường val pat = expr, điều bên trái dấu bằng chỉ là mẫu.

Việc sản xuất Enumerator trong spec cú pháp cho thấy rằng mệnh đề trong một cho-expr có thể là một máy phát điện (a <- b), bảo vệ if cond hoặc val def a = b.

Các phần có thể là biểu thức tùy ý là b (như được cho bên phải của <-=) và điều kiện.

Responder.exec tận dụng lợi thế của điều kiện để thực thi mã tùy ý, trong khi đánh giá trivially đến true.

Điều đó có nghĩa bạn có thể làm tùy ý tác dụng phụ từ một điều kiện:

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

Tương tự, desugars def val như sau:

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

Chờ, thực sự?

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

Bạn sẽ cần một repl gần đây để làm điều này:

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  

tôi thấy hai lời gọi của bản đồ, cho biểu thức trung gian và cho năng suất.

Khi kiểm tra kỹ hơn, anonfun đầu tiên không phải là Int => Int (ví dụ: a+1) nhưng là Int => (Int,Int).

Vì vậy, val chúng tôi đã giới thiệu chỉ được truyền đi xung quanh như một phần của bộ đồ.

Các vấn đề liên quan