Получение десугализованной части выражения Scala для/понимания?
Кто-нибудь знает, как получить ((только w60 > часть) desugared перевод выражения for/comprehension, прежде чем он попытается скомпилировать в REPL (или компиляторе)?
Единственное, что я нашел до сих пор, это флаг "-print" компилятора, который дает вам полный перевод Scala...
Ответы
Ответ 1
Кажется, что не существует каких-либо возможностей для выражения "для/понимания" desugar непосредственно в REPL. Но в качестве альтернативы можно использовать некоторые параметры компилятора Scala, такие как "-print" или для простых выражений "Xprint: typer -e"
Пример:
Чтобы получить вывод desugard из файла, используйте флаг "-print":
# scala -print file.scala
Чтобы отбросить простое однострочное выражение, используйте флаг "-print: typer -e":
# scala -Xprint:typer -e "for (i <- 0 to 100) yield i"
Ответ 2
Как я уже сказал в другой теме, scalac -print
выводит scala код, а не java. Он переводит все 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)}
Вложенные fors будут переведены на вложенные конструкции flatMap/map
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
}
}
Итак, нет волшебства
Ответ 3
Как насчет макроса?
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
.
Ответ 4
Чтобы увидеть результат после простой десурагирования, используйте параметр -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
Опция -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>
Ответ 5
В 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)
Ответ 6
В Intellij есть функция, называемая Объяснить Scala", которая делает много шумирования, включая расширение для понимания в map/flatMap/filter непосредственно в файле, который вы редактируете.
Обратите внимание, что поскольку IntelliJ 2017.1 теперь называется "Desugar Scala Code" и находится в меню "Code" (спасибо Mikaël за информацию).
![IntelliJ Desugar Scala]()