首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >获取Scala for/comprehension表达式的去糖化部分?

获取Scala for/comprehension表达式的去糖化部分?
EN

Stack Overflow用户
提问于 2012-03-27 22:19:26
回答 6查看 10.2K关注 0票数 32

有谁知道如何在实际尝试在REPL (或编译器)中编译一个for/compiler表达式之前获得(仅限Scala部分)去糖化的翻译?

到目前为止,我发现的唯一一件事就是编译器"-print“标志,但它给出了完整的Scala转换…

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-03-27 23:12:06

在REPL中,似乎不存在直接对"for/comprehension“表达式进行去糖化的可能性。但作为替代,可以使用一些Scala编译器选项,如"-print“或用于简单表达式"Xprint:typer -e”

示例:

要从文件中获取desugard输出,请使用"-print“标志:

# scala -print file.scala

要去掉一个简单的单行表达式,请使用"-Xprint:typer -e“标志:

# scala -Xprint:typer -e "for (i <- 0 to 100) yield i"
票数 26
EN

Stack Overflow用户

发布于 2012-03-27 22:35:12

正如我在另一个主题中所说的,scalac -print打印的是scala代码,而不是java。它将所有与java不直接兼容的scala关键字转换为普通的scala代码。不可能让编译器只翻译部分afaik。但从根本上讲,for-comprehension总是以同样的方式被翻译。

像这样的简单的for/yield

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

所以绝对没有魔法

票数 36
EN

Stack Overflow用户

发布于 2013-11-05 02:21:31

宏怎么样?

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命令加载的外部文件中定义宏。

票数 25
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9891407

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档