3

Scala에서 함수 정의를 인쇄 할 수 있는지 궁금합니다. Scala에서는 함수가 객체로 취급됩니다. 예를 들어Scala에서 함수 정의를 인쇄 할 수 있습니까?

:

스칼라> 발 splitFunction = (값 : 문자열) => {value.split ("")}

splitFunction: String => Array[String] = <function1> 

스칼라 대화식 쉘 splitFunction 입력 파라미터를 갖는 것을 나타낸다 문자열과 문자열 배열을 반환합니다. 실제로 function1이 여기에 나타내는 것은 무엇입니까?

splitFunction의 정의를 인쇄하거나 검색 할 수 있습니까?

우리는 파이썬에서 동일한 얻을 수 있습니다 Is it possible to print a function as a string in Python?

업데이트 : 아파치 스파크에서 , RDD 계보 또는 DAG 각 단계에서 부모 RDD 및 변환에 대한 정보를 저장합니다. 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>이다, 그래서 우리는 단지 하나 개의 인자를 몇 가지 기능이 있다고 말한다.

함수의 정의를 가져올 수없는 이유는 스칼라가 컴파일 되었기 때문입니다. 함수에 대한 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이 내가 API가 거기하다고 생각합니다 (JVM에서 구현을 검색하는 것보다는 읽을 수 (물론 주석 광산) 이미 ,하지만 그것은 디버거를위한 것입니다), 그리고 2) Scala/Java로 코드를 디 컴파일하십시오. 그 자체로 불가능한 것은 아니지만 아무도 그것을했다고 생각하지 않습니다. (실제로는 왜 그렇게할까요?)

이제 모든 스칼라 익명 함수는 코드를 저장하고 toString을 출력하면 출력되지만, 다시 말해서 출력 할 이유가 없습니다. 디버깅을 목적으로 구현을 원한다고하더라도, 소스 코드를 가지고 있으며 클래스 파일의 행 번호를 사용하여 점프 할 수 있으며, 저장하려는 경우 클래스 파일에 이미 저장되어 있습니다.

당신은 정말는, 그것이 가능하려면, 이론적으로,

stringF { arg => body } // BTW: say bye to type inference 
을 켤 수있는 (수신 거부) 매크로 (또는 컴파일러 플러그인)

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 = ??? 

을 정의 경우

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는 프로그래밍 언어입니다. "컴파일 된 프로그래밍 언어"와 같은 것은 없습니다. 프로그래밍 언어는 컴파일되거나 해석되지 않습니다. 프로그래밍 언어 *는 *입니다. 편집 및 해석은 언어가 아닌 컴파일러 또는 해석기 (duh)의 특성입니다. 모든 언어를 컴파일하고 모든 언어를 해석 할 수 있습니다. 스칼라가 컴파일 된 구현물을 가지고 있다는 사실은 함수의 소스 코드에 액세스 할 수 있는지 여부와 아무런 관련이 없습니다. 소스 코드를 저장할 수 있습니다 ... –

+0

... 인터프리터 또는 컴파일러를 사용하여 소스 코드를 저장하는지 여부에 관계없이 함수의. 스칼라 언어 스펙이 'toSource' 메소드를 갖기 위해 필요한 함수라면 컴파일러는 함수의 소스 코드를 정적 문자열 상수로 포함하는'toSource' 메소드로 익명 클래스를 생성합니다. 현재의 모든 주요 주류 ECMAScript 구현이 컴파일되지만 ECMA-262 사양에 따르면 단순히 모든 기능의 소스 코드를 인쇄 할 수 있습니다. –