是否可以在Scala中打印函数的定义
我想知道我们是否可以在Scala中打印函数的定义。一个函数被视为Scala中的一个对象。是否可以在Scala中打印函数的定义
例如:
阶> VAL splitFunction =(值:字符串)=> {value.split(”“)}
splitFunction: String => Array[String] = <function1>
以上,Scala的交互式shell表示splitFunction具有输入参数字符串,它返回字符串数组。真正的功能1在这里表示什么?
是否可以打印或检索splitFunction的定义?
我们可以实现在同一蟒: Is it possible to print a function as a string in Python?
更新: 在Apache的星火,RDD血统或DAG存储有关在每个阶段父RDD和转换信息。我有兴趣获取一个函数的定义(甚至是lambda函数或匿名函数),用作flatMap或map等变换的参数。
例如:文件 - DebugTest.scala
val dataRDD = sc.textFile("README.md")
val splitFunction = (value : String) => {value.split(" ")}
val mapRDD = dataRDD.map(splitFunction)
println(mapRDD.toDebugString)
输出:
(1) MapPartitionsRDD[2] at map at DebugTest.scala:43 []
| README.md MapPartitionsRDD[1] at textFile at DebugTest.scala:41 []
| README.md HadoopRDD[0] at textFile at DebugTest.scala:41 []
从上面的输出中,我能理解进行什么变革,但无法理解或用作splitFunction定义检索“地图”变换中的一个参数。有没有办法检索或打印它?
号(一般)
它之所以说<function1>
是因为没有被赋予的功能没有很好字符串表示,所以我们只是说,它的一些功能,它有一个参数。
你无法获得函数定义的原因是因为Scala被编译。在JVM字节码的功能已经是相当不可读(评论我的,当然)
aload_1 // Load the second argument (of reference type) onto the stack (the first is this function object)
checkcast #mm // Where mm is an index into the class constant pool, representing a reference to the class String (cast inserted because this is a generic method)
ldC#nn // Where nn is an index representing the string " "
invokevirtual #oo // Where oo is another index, this time representing String::split
areturn // Return whatever's left on the stack
A“显示功能实现”功能,就必须1)检索的JVM实现(我相信有一个API为,但它意味着调试器),然后2)将代码反编译为Scala/Java。这不是不可能的,本身,但我不认为任何人都做到了(真的,为什么你会怎么做呢?)现在
,将有可能为每斯卡拉匿名函数来只存储其代码和覆盖toString
来输出它,但是,再次,没有理由这样做。即使您希望实现用于调试目的,您也有机会获得源代码,并且可以使用类文件中的行号跳转到该文件,如果要存储它,它已存储在类文件中。
如果你真的想要它,它是可能的,在理论上定义(选入)宏(甚至是编译器插件)
import language.experimental.macros
import reflect.macros.whitebox.Context
def stringF(f: Any): Any = macro stringF_impl
def stringF_impl(c: whitebox.Context)(f: c.Tree): c.Tree = ???
那会使
stringF { arg => body } // BTW: say bye to type inference
到
new Function1[A, R] {
override def apply(arg: A) = body
override def toString() = "{ arg => body }" // This part is not there normally
}
但同样,我还没有听说有人做,并且有没有理由尝试。
谢谢你的详细回复。欣赏它。我已经用目标和其他信息更新了我的问题。让我知道你是否有任何解决方案来实现相同的目标。 – aagora
我强烈不同意你的推理。斯卡拉不是“编译”的。 Scala是一种编程语言。没有像“编译的编程语言”这样的东西。编程语言不被编译或解释。编程语言*是*。汇编和解释是编译器或解释器(杜)的特点,而不是语言。每种语言都可以编译,每种语言都可以解释。 Scala恰好具有一些编译实现的事实与您是否可以访问函数的源代码无关。无论您使用解释器还是编译器来存储源代码,您都可以存储函数的源代码... –
...。如果Scala语言规范要求函数具有'toSource'方法,那么编译器会简单地使用'toSource'方法生成一个匿名类,该方法将函数的源代码作为静态字符串常量进行包含。例如,所有现有的主流ECMAScript实现都已编译完毕,但它们都可以打印函数的源代码,仅仅是因为ECMA-262规范说他们必须这样做。 –