2012-03-27 1 views
17

Кто-нибудь знает, как получить (только часть Scala) desugared перевод выражения for/comprehension, прежде чем он попытается скомпилировать в REPL (или компиляторе)?Получение десугатной части выражения Scala for/assrehension?

Единственное, что я нашел до сих пор является флаг «-print» компилятор, но это дает вам полный Scala перевод ...

ответ

21

Это, кажется, не существует никаких возможностей к выражению desugar «для/понимания» непосредственно в REPL. Но в качестве альтернативы можно использовать некоторые опции компилятора 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. Кроме того, вы можете использовать это с REPL, как этот 'scala -Xprint: parser'. Тем не менее, он также покажет весь код обертки, который REPL ставит вокруг вашего кода. – mgd

30

Как я уже говорил в другой теме, scalac -print печатает вне Код SCALA, не Ява. Он переводит все ключевые слова scala, которые напрямую не совместимы с java для обычного кода 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

+0

+1 Я искал код, который не был выделен, а не флаги. – ziggystar

14

Чтобы увидеть результат после того, как простой desugaring использовать -Xprint:parser вариант.

Если этот простой входной файл с именем test.scala:

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

Затем его компиляции с помощью scalac -Xprint:parser распечатывает:

$ 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> сделать это:

$ 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 

01 Опциятакже применима к 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 

Это может быть использован непосредственно в РЕПЛ, согласно вашему запросу:

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

В Scala 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 имеет функцию под названием «Explain Scala», что делает много desugaring включая расширение для постижений Into карты/flatMap/фильтр непосредственно в файл, который вы редактируете.

Обратите внимание, что поскольку IntelliJ 2017.1 это теперь называется «Код шутера Desugar» и находится в меню «Код» (спасибо Mikaël за информацию).

IntelliJ Desugar Scala

+0

Не работает в моем случае. –

+0

Подробно пожалуйста? – ChoppyTheLumberjack

+0

С последней версией IntelliJ он снова работает. Но учтите, что не написано «Объяснить Скала», но «Код Шурага Скала», –