我想看看f在map/flatmap中传递的函数,但没有运气.我抛出一个例外,看到任何迹象f,没有用.那是什么功能?它是如何在幕后产生的?
Exception in thread "main" java.lang.RuntimeException
at x.x.Main$A.getInt(Empty.scala:8)
at x.x.Main$A.flatMap(Empty.scala:10)
object Main extends App {
class A {
def getInt: Int = throw new RuntimeException
def map(f: Int => Boolean): Boolean = f(getInt)
def flatMap(f: Int => Boolean): Boolean = f(getInt)
}
for {
x <- new A
y <- new A
} yield x == y
}
Run Code Online (Sandbox Code Playgroud)
sen*_*nia 11
你的理解的等价代码
for {
x <- new A
y <- new A
} yield x == y
Run Code Online (Sandbox Code Playgroud)
是这样的:
new A().flatMap{ x => new A().map{ y => x == y } }
Run Code Online (Sandbox Code Playgroud)
您可以使用scalac -Xprint:parser main.scala从您的代码生成代码for-comprehension.在这种情况下,你会得到这个:
new A().flatMap(((x) => new A().map(((y) => x.$eq$eq(y)))))
Run Code Online (Sandbox Code Playgroud)
如果没有像这样的附加宏,你也可以在REPL中获取它:
import reflect.runtime.universe._
show{ reify{
for {
x <- new A
y <- new A
} yield x == y
}.tree }
// new $read.A().flatMap(((x) => new $read.A().map(((y) => x.$eq$eq(y)))))
Run Code Online (Sandbox Code Playgroud)
KCh*_*oux 11
如果您使用的是Scala 2.10或更高版本,则可以使用以下命令在repl中显示desugared scala代码:
import scala.reflect.macros.Context // use BlackboxContext if you're in 2.11
import scala.reflect.runtime.universe._
import scala.language.experimental.macros
def _desugar(c : Context)(expr : c.Expr[Any]): c.Expr[Unit] = {
import c.universe._
println(show(expr.tree))
reify {}
}
def desugar(expr : Any): Unit = macro _desugar
Run Code Online (Sandbox Code Playgroud)
这将允许您传入代码块,并查看它们转换成的内容.对于您的示例,在repl中:
scala> class A {
| def getInt: Int = throw new RuntimeException
| def map(f: Int => Boolean): Boolean = f(getInt)
| def flatMap(f: Int => Boolean): Boolean = f(getInt)
| }
defined class A
scala> desugar {
| for {
| x <- new A
| y <- new A
| } yield x == y
| }
new $line15.$read.$iw.$iw.$iw.$iw.A().flatMap(((x: Int) => new $line15.$read.$iw.$iw.$iw.$iw.A().map(((y: Int) => x.==(y)))))
Run Code Online (Sandbox Code Playgroud)
这有点乱,因为repl会创建几个中间临时变量,但是你可以看到发生了什么的结构.
new A().flatMap { (x: Int) =>
new A().map { (y: Int) =>
x == y
}
}
Run Code Online (Sandbox Code Playgroud)
这适用于大多数表达式,并允许您检查实际代码在编译期间将转换为什么.
我应该指出我的源代码 - 我的版本desugar是在github上的Macrocosm repo中找到的函数的略微修改版本.