6

当我在理解中使用 val 时,我收到警告:

警告:不推荐使用用于理解的 val 关键字

尽管在规范的语法附录中产生。

这表明当我做类似的事情时

for (x <- xs; a = x)

我并没有真正引入变量,例如如果我做类似的事情

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

像往常一样,大括号开始一个新的范围,我可以在其中引入一个新的 val,甚至是一个新的隐式。

我到底在做什么a

我在消耗堆栈空间吗?堆?其他类型的别名?

4

1 回答 1

7

就像一个普通的val pat = expr定义一样,等号左边的东西只是一个模式。

语法规范中的 Enumerator 产生式表明 for-expr 中的子句可以是 generator (a <- b)、 guardif cond或 val def a = b

可以是任意表达式的部分是(在andb的右侧给出)和条件。<-=

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 脱糖如下:

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]

您需要最近的 repl 才能执行此操作:

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 不是 a Int => Int(ie, a+1) 而是 a Int => (Int,Int)

所以我们介绍的 val 只是作为元组的一部分传递。

于 2012-12-29T23:52:09.843 回答