2012-03-27 7 views

Odpowiedz

21

To nie wydaje się żadnych możliwości istnieje do wyrzucania wyrażeń "za/zrozumienie" bezpośrednio w REPL. Ale jako alternatywny można wykorzystać niektóre opcje kompilatora Scala jak „-print” lub dla prostych wyrażeń „xprint: typer -e”

Przykład:

Aby uzyskać wyjście desugard z pliku użyć „-Print "Flaga:

# scala -print file.scala 

Aby desugar prostego wyrażenia jednego-liner, użyj "-Xprint: typer -e" flag

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

Przede wszystkim powinieneś użyć '-Xprint: parser', aby zobaczyć tylko usuwanie. Możesz również użyć tego z REPL, tak jak ten 'scala -Xprint: parser'. Jednak ujawni on również cały kod opakowania, który REPL umieszcza w twoim kodzie. – mgd

30

Jak już powiedziałem w innym temacie, scalac -print wypisuje Kod Scala, nie Jawa. To tłumaczy wszystkie słowa kluczowe scala, które nie są bezpośrednio zgodne z java do normalnego kodu scala. Nie można pozwolić, aby kompilator tłumaczył tylko części afaik. Ale zasadniczo zrozumienie zawsze jest tłumaczone w ten sam sposób.

prosty do/z wydajnością jak ten

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

będą tłumaczone

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

Bez wydajnością

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

do

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

zagnieżdżone Fors będą tłumaczone na zagnieżdżonego flatMap/mapa konstruuje

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

będą tłumaczone na

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

więc nie ma absolutnie żadnego magicznego

+6

Mój zły, masz absolutną rację! Znalazłem także flagę kompilatora -e dla prostych wyrażeń, takich jak: scala -Xprint: typer -e "val i = 1" – IODEV

+0

+1 Szukałem wyodrębnionego kodu, a nie flag. – ziggystar

14

Aby zobaczyć wynik po użyciu prosty desugaring na -Xprint:parser Opcja.

Jeśli to prosty plik wejściowy o nazwie test.scala:

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

Następnie kompilowanie go przy użyciu scalac -Xprint:parser drukuje się:

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

Aby uzyskać pełną listę faz kompilatora zastosowanie do -Xprint:<phase> to zrobić:

$ 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 01 Opcjama również zastosowanie do scala, a tym samym do REPL.Jednak zobaczysz także cały kod opakowania, który również wstawia 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

Co z makrem?

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 

ten może być stosowany bezpośrednio w REPL, jak na swój wniosek:

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

działa również na innych dowolnych wyrażeń.

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

To jest chyba najbliżej dostaniesz co prosisz bez konieczności kompilowania lub zrzutu danych do pliku w dowolnym momencie. Makro można zdefiniować bezpośrednio w REPL lub w zewnętrznym pliku załadowanym poleceniem :load.

2

w Scala 2.11, możliwe jest również użycie 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 posiada funkcję o nazwie „Explain Scala”, który robi wiele z desugaring tym rozszerzenie dla listowe na mapę/flatMap/filtr bezpośrednio w plik, który edytujesz.

Należy pamiętać, że od wersji IntelliJ 2017.1 nazywa się to teraz "Kod Scala Desugara" i znajduje się w menu "Kod" (dzięki Mikaël za informacje).

IntelliJ Desugar Scala

+0

Nie działa w moim przypadku. –

+0

Szczegóły proszę? – ChoppyTheLumberjack

+0

Od ostatniej wersji IntelliJ działa ponownie. Należy jednak pamiętać, że nie jest napisane "Wyjaśnij Scala", ale "Kod Scala Desugara" –

Powiązane problemy