2012-03-27 1 views
17

Weiß jemand, wie man die (nur im Scala-Teil) entzuckerte Übersetzung eines for/Verständnisausdrucks erhält, bevor er tatsächlich versucht, in der REPL (oder dem Compiler) zu kompilieren?Den entzuckerten Teil eines Scala für/Verständnisausdrucks bekommen?

Das einzige, was ich bisher gefunden habe, ist der Compiler „-Druck“ Flagge aber das gibt Ihnen die vollständige Übersetzung Scala ...

Antwort

21

ist also übersetzt Es scheint nicht alle Möglichkeiten vorhanden Entwendungen für "Verständnis" -Ausdrücke direkt innerhalb der REPL. Aber als Alternative kann man einige Scala Compiler-Optionen wie „-Druck“ verwenden oder für einfache Ausdrücke „Xprint: typer -en“

Beispiel:

Um die desugard Ausgabe aus einer Datei zu erhalten nutzt die „-Druck "flag:

# scala -print file.scala 

Um desugar einen einfachen ein-liner Ausdruck verwenden, um den "-Xprint: typer -en flag":

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

Als erstes sollten Sie den '-Xprint: parser' verwenden, um nur das Entwerfen zu sehen. Sie können dies auch mit der REPL verwenden, wie zB 'scala -Xprint: parser'. Es wird jedoch auch den gesamten Wrapper-Code offenlegen, den die REPL Ihren Code bereitstellt. – mgd

30

Wie ich bereits in dem anderen Thema gesagt, scalac -print druckt scala-Code, nicht Java. Es übersetzt alle Scala-Schlüsselwörter, die nicht direkt mit Java kompatibel sind, mit normalem Scala-Code. Es ist nicht möglich, den Compiler nur Teile afaik übersetzen zu lassen. Aber im Grunde wird ein Verständnis immer auf die gleiche Weise übersetzt.

Ein einfacher für/Ertrag wie dieser Und

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

zu

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

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

wird

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

übersetzt

Nested fors wird verschachtelte flatMap übersetzt werden/map-Konstrukten

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

wird

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

es absolut Magie kein

+6

Meine schlechte, du hast absolut recht! Ich fand auch das Compiler-e Flag für einfache Ausdrücke wie: scala -Xprint: type -e "val i = 1" – IODEV

+0

+1 Ich suchte nach dem entzuckerten Code, nicht nach den Flags. – ziggystar

14

Um das Ergebnis zu sehen, nachdem die einfachen EntzuckernverwendenOption.

Wenn Sie diese einfache Eingabedatei test.scala genannt:

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

es dann kompilieren scalac -Xprint:parser Drucke mit heraus:

$ 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))))) 
    } 
} 

Um eine vollständige Liste der Compiler-Phasen für -Xprint:<phase> tun diese:

$ 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 

Die -Xprint:<phase> Option gilt auch für scala und damit für die REPL.Sie werden jedoch den gesamten Wrappercode sehen, den die REPL ebenfalls einfügt.

$ 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

Wie wäre es mit einem Makro?

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 

Dies kann in der REPL direkt verwendet werden, wie pro Ihre Anfrage:

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]) 

Es funktioniert auch auf andere beliebige Ausdrücke.

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)) 
} 

Dies ist wahrscheinlich die nächst Sie bekommen, was Sie ohne jemals gefragt sind, die die Daten in eine Datei an einem beliebigen Punkt zu kompilieren oder Dump. Sie können das Makro direkt in der REPL oder in einer externen Datei definieren, die mit dem Befehl :load geladen wird.

2

In scala 2.11 ist es auch möglich, 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 hat eine Funktion namens "Explain Scala", die eine Menge Entzuckern tut auch für Comprehensions in Karte erweitern/flatMap/Filter direkt in die Datei, die Sie bearbeiten.

Bitte beachten Sie, dass es seit IntelliJ 2017.1 jetzt "Desugar Scala Code" heißt und sich im Menü "Code" befindet (danke Mikaël für die Info).

IntelliJ Desugar Scala

+0

Funktioniert nicht in meinem Fall. –

+0

Details bitte? – ChoppyTheLumberjack

+0

Seit der letzten Version von IntelliJ funktioniert es wieder. Beachten Sie jedoch, dass nicht "Scala erklären", sondern "Desugar Scala Code" geschrieben wurde. –

Verwandte Themen