What is the map / flatmap function used for understanding?

I want to see the function f , which is passed to map / flatmap, but not luck. I selected an exception to see any signs of f did not work. What is this function? how is it created behind the scenes?

 Exception in thread "main" java.lang.RuntimeException at xxMain$A.getInt(Empty.scala:8) at xxMain$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 } 
+6
source share
2 answers

Equivalent code for your understanding

 for { x <- new A y <- new A } yield x == y 

as follows:

 new A().flatMap{ x => new A().map{ y => x == y } } 

You can use scalac -Xprint:parser main.scala to get the code generated from your for-comprehension . In this case, you will receive the following:

 new A().flatMap(((x) => new A().map(((y) => x.$eq$eq(y))))) 

You can also get it in REPL without adding a macro as follows:

 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))))) 
+11
source

If you are using Scala 2.10 or later, you can use the following to display the Scala uncooled code in repl:

 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 

This will allow you to go through the code blocks and see what they translate to. For your example, in 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))))) 

This is a bit dirty because repl creates some intermediate temporary variables, but you can see the structure of what is happening.

 new A().flatMap { (x: Int) => new A().map { (y: Int) => x == y } } 

This works for most expressions and allows you to check what the actual code translates to at compile time.

Update

I have to point out my source - my version of desugar is a slightly modified version of the function found in the Macrocosm repository on github.

+11
source

All Articles