当我在for-comprehension中使用val时,我收到警告:
警告:不推荐使用val关键字进行理解
尽管在规范的语法附录中生成了
这表明当我做
之类的事情时for (x <- xs; a = x)
我并没有真正引入变量,例如,如果我执行类似
的操作for (x <- xs) yield { implicit val a = x; /* more */ }
其中,像往常一样,大括号开始一个新的范围,我可以引入一个新的val,甚至是一个新的隐式。
我对a
做了什么?
我是否在消耗堆栈空间?堆?其他一些别名?
答案 0 :(得分:7)
与普通的val pat = expr
定义一样,等号左边的东西只是一种模式。
语法规范中的Enumerator生成显示for-expr中的子句可以是生成器(a <- b)
,后卫if cond
或val def a = b
。
可以是任意表达式的部分是b
(如<-
和=
右侧所示)和条件。
Responder.exec
利用条件执行任意代码,同时对true
进行简单评估。
这意味着你可以从条件中做任意的副作用:
// 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)
同样,val def desugars如下:
tmp <- xs
a = f(tmp) // some arbitrary function of tmp
// amounts to
(tmp, a) <- for (x@tmp <- xs) yield { val x0@a=f(tmp); (x, x0) }
等等,真的吗?
scala> def f(vs: List[Int]) = for (a <- vs; b = a+1) yield b
f: (vs: List[Int])List[Int]
您需要最近的代理才能执行此操作:
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
我看到两个map的调用,用于中间表达式和yield。
进一步检查时,第一个anonfun不是Int => Int
(即a+1
),而是Int => (Int,Int)
。
所以我们引入的val只是作为元组的一部分传递。