3

我想知道我们是否可以在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定义检索“地图”变换中的一个参数。有没有办法检索或打印它?

回答

4

号(一般)

它之所以说<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 
} 

但同样,我还没有听说有人做,并且有没有理由尝试。

+0

谢谢你的详细回复。欣赏它。我已经用目标和其他信息更新了我的问题。让我知道你是否有任何解决方案来实现相同的目标。 – aagora

+0

我强烈不同意你的推理。斯卡拉不是“编译”的。 Scala是一种编程语言。没有像“编译的编程语言”这样的东西。编程语言不被编译或解释。编程语言*是*。汇编和解释是编译器或解释器(杜)的特点,而不是语言。每种语言都可以编译,每种语言都可以解释。 Scala恰好具有一些编译实现的事实与您是否可以访问函数的源代码无关。无论您使用解释器还是编译器来存储源代码,您都可以存储函数的源代码... –

+0

...。如果Scala语言规范要求函数具有'toSource'方法,那么编译器会简单地使用'toSource'方法生成一个匿名类,该方法将函数的源代码作为静态字符串常量进行包含。例如,所有现有的主流ECMAScript实现都已编译完毕,但它们都可以打印函数的源代码,仅仅是因为ECMA-262规范说他们必须这样做。 –

相关问题