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à =
) 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ộ đồ.