2012-03-27 13 views
17

有没有人知道在实际尝试在REPL(或编译器)中进行编译之前,如何获得(仅限Scala部分)for/comprehension表达式的desugared转换?获取Scala的desugared部分for/comprehension表达式?

我到目前为止发现的唯一的事情就是编译器“-print”的标志,但是,让你充分斯卡拉翻译...

回答

21

这似乎魔法并不存在任何可能性直接在REPL中解析“for/comprehension”表达式。但是作为替代可以使用一些Scala编译器选项,如“-print”或简单表达式“的Xprint:打字员-e”

例子:

从文件中得到desugard输出使用“-print “标志:

# scala -print file.scala 

要desugar一个简单的一行表达,使用 ”-Xprint:导电型测量仪-e“ 标志:

# scala -Xprint:typer -e "for (i <- 0 to 100) yield i" 
+2

首先,您应该使用'-Xprint:parser'来仅查看desugaring。另外,你可以像这样'scala -Xprint:parser'在REPL中使用它。但是,它还会显示REPL在您的代码中放置的所有包装代码。 – mgd 2013-10-30 07:30:05

30

正如我已经在其他主题中说,scalac -print打印出Scala代码,而不是java的。它将所有不与java直接兼容的scala关键字转换为正常的scala代码。不可能让编译器只翻译部分afaik。但基本上,理解总是以相同的方式翻译。

一个简单的用于/像这样

for(x <- List(1,2,3)) yield x*x 

产量将被转换为

List(1,2,3).map {x => x*x} 

而且没有屈服

for(x <- List(1,2,3)) println(x) 

List(1,2,3).foreach{x => println(x)} 

嵌套维权将被转换为嵌套flatMap /图构建

for(x <- List(1,2,3); y <- List(4,5,6)) yield x*y 

将被转换为

List(1,2,3).flatMap { x => 
    List(4,5,6).map { y => 
    x*y 
    } 
} 

所以绝对不会有

+6

我的不好,你是绝对正确的!我还发现了一个简单表达式的编译器-e标志,例如:scala -Xprint:typer -e“val i = 1” – IODEV 2012-03-27 14:49:04

+0

+1我正在搜索desugared代码,而不是标志。 – ziggystar 2013-08-23 13:08:20

14

看到的结果简单脱糖使用后选项。

如果您在本简单的输入文件命名为test.scala

$ scalac -Xprint:parser test.scala 
[[syntax trees at end of     parser]] // test.scala 
package <empty> { 
    object Test extends scala.AnyRef { 
    def <init>() = { 
     super.<init>(); 
    () 
    }; 
    List(1, 2, 3).flatMap(((x) => List(4, 5, 6).map(((y) => x.$times(y))))) 
    } 
} 

要获得适用的编译器过程的完整列表,以-Xprint:<phase>做到这一点:

object Test { 
    for(x <- List(1,2,3); y <- List(4,5,6)) yield x*y 
} 

然后使用scalac -Xprint:parser打印出编译它:

$ scalac -Xshow-phases 
      phase name id description 
      ---------- -- ----------- 
       parser 1 parse source into ASTs, perform simple desugaring 
        namer 2 resolve names, attach symbols to named trees 
     packageobjects 3 load package objects 
        typer 4 the meat and potatoes: type the trees 
       patmat 5 translate match expressions 
     superaccessors 6 add super accessors in traits and nested classes 
      extmethods 7 add extension methods for inline classes 
       pickler 8 serialize symbol tables 
       refchecks 9 reference/override checking, translate nested objects 
      selectiveanf 10 
      selectivecps 11 
       uncurry 12 uncurry, translate function values to anonymous classes 
       tailcalls 13 replace tail calls by jumps 
      specialize 14 @specialized-driven class and method specialization 
      explicitouter 15 this refs to outer pointers, translate patterns 
       erasure 16 erase types, add interfaces for traits 
      posterasure 17 clean up erased inline classes 
       lazyvals 18 allocate bitmaps, translate lazy vals into lazified defs 
      lambdalift 19 move nested functions to top level 
      constructors 20 move field definitions into constructors 
       flatten 21 eliminate inner classes 
        mixin 22 mixin composition 
       cleanup 23 platform-specific cleanups, generate reflective calls 
        icode 24 generate portable intermediate code 
       inliner 25 optimization: do inlining 
inlineExceptionHandlers 26 optimization: inline exception handlers 
       closelim 27 optimization: eliminate uncalled closures 
        dce 28 optimization: eliminate dead code 
        jvm 29 generate JVM bytecode 
       terminal 30 The last phase in the compiler chain 

The -Xprint:<phase>选项也适用于scala,因此适用于REPL。但是,您将看到REPL插入的所有包装器代码。

$ scala -Xprint:parser 
Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_25). 
Type in expressions to have them evaluated. 
Type :help for more information. 

<..a lot of initialisation code printed..> 

scala> object Test { 
    | for(x <- List(1,2,3); y <- List(4,5,6)) yield x*y 
    | } 
[[syntax trees at end of     parser]] // <console> 
package $line3 { 
    object $read extends scala.AnyRef { 
    def <init>() = { 
     super.<init>(); 
    () 
    }; 
    object $iw extends scala.AnyRef { 
     def <init>() = { 
     super.<init>(); 
     () 
     }; 
     object $iw extends scala.AnyRef { 
     def <init>() = { 
      super.<init>(); 
     () 
     }; 
     object Test extends scala.AnyRef { 
      def <init>() = { 
      super.<init>(); 
      () 
      }; 
      List(1, 2, 3).flatMap(((x) => List(4, 5, 6).map(((y) => x.$times(y))))) 
     } 
     } 
    } 
    } 
} 

[[syntax trees at end of     parser]] // <console> 
package $line3 { 
    object $eval extends scala.AnyRef { 
    def <init>() = { 
     super.<init>(); 
    () 
    }; 
    lazy val $result = $line3.$read.$iw.$iw.Test; 
    val $print: String = { 
     $read.$iw.$iw; 
     "".$plus("defined module ").$plus("Test").$plus("\n") 
    } 
    } 
} 

defined module Test 

scala> 
17

宏如何?

import scala.reflect.macros.Context 
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) = macro _desugar 

这可以直接在REPL使用,按您的要求:

scala> desugar { for(i <- List(1,2,3,4,5)) yield i } 
immutable.this.List.apply[Int](1, 2, 3, 4, 5).map[Int, Any](((i: Int) => 
i))(immutable.this.List.canBuildFrom[Int]) 

scala> desguar { for(i <- (0 to 10) if (i > 5)) yield i } 
scala.this.Predef.intWrapper(0).to(10).withFilter(((i: Int) => i.>(5))).map[Int, 
Any](((i: Int) => i))(immutable.this.IndexedSeq.canBuildFrom[Int]) 

它也适用于其它任意表达式。

scala> desugar { 
    | val x = 20 
    | val y = 10 
    | println(x + y) 
    | } 
{ 
    val x: Int = 20; 
    val y: Int = 10; 
    scala.this.Predef.println(x.+(y)) 
} 

这可能是最接近你要求的东西,而不需要在任何时候将数据编译或转储到文件。您可以直接在REPL中或在使用:load命令加载的外部文件中定义宏。

2

在阶2.11,也可以使用quasiquotes

val universe: scala.reflect.runtime.universe.type = scala.reflect.runtime.universe 
import universe._ 
val tree = q""" 
    val x = 20 
    val y = 10 
    println(x + y) 
""" 
println(tree) 
2

的Intellij有一个称为特征,做脱糖的LOT包括直接在扩大推导成图/ flatMap /过滤器“Explain Scala”你正在编辑的文件。

请注意,自IntelliJ 2017.1现在称为“Desugar Scala代码”,并在“代码”菜单中(感谢Mikaël的信息)。

IntelliJ Desugar Scala

+0

在我的情况下不起作用。 – 2017-03-23 18:32:53

+0

请详细说明? – ChoppyTheLumberjack 2017-05-22 17:25:20

+0

自IntelliJ的最后一个版本开始工作了。但请注意,它不是写成“解释Scala”,而是“Desugar Scala Code” – 2017-05-23 06:25:12