[SCALA] 매크로에서 익명 클래스의 방법과 구조 유형을 얻기
SCALA매크로에서 익명 클래스의 방법과 구조 유형을 얻기
우리는 어떤 종류의 회원 또는 방법으로 익명의 클래스를 정의하고 정적 등 그 방법과 구조 유형이 2.10에서 매크로 시스템과 가능한 한 입력 된 사용자들은 클래스의 인스턴스를 생성하는 매크로를 작성한다고 가정. 0 및 형식 멤버 부분은 매우 쉽습니다 :
object MacroExample extends ReflectionUtils {
import scala.language.experimental.macros
import scala.reflect.macros.Context
def foo(name: String): Any = macro foo_impl
def foo_impl(c: Context)(name: c.Expr[String]) = {
import c.universe._
val Literal(Constant(lit: String)) = name.tree
val anon = newTypeName(c.fresh)
c.Expr(Block(
ClassDef(
Modifiers(Flag.FINAL), anon, Nil, Template(
Nil, emptyValDef, List(
constructor(c.universe),
TypeDef(Modifiers(), newTypeName(lit), Nil, TypeTree(typeOf[Int]))
)
)
),
Apply(Select(New(Ident(anon)), nme.CONSTRUCTOR), Nil)
))
}
}
(ReflectionUtils 내 생성자 방법을 제공하는 편리한 특성입니다.)
이 매크로는 우리가 문자열 리터럴로 익명 클래스의 타입 멤버의 이름을 지정할 수 있습니다 :
scala> MacroExample.foo("T")
res0: AnyRef{type T = Int} = $1$$1@7da533f6
이 적절하게 입력있어합니다. 예상대로 우리는 모든의 작업을 확인할 수 있습니다 :
scala> implicitly[res0.T =:= Int]
res1: =:=[res0.T,Int] = <function1>
이제 우리는 방법과 같은 일을하려고한다고 가정 :
def bar(name: String): Any = macro bar_impl
def bar_impl(c: Context)(name: c.Expr[String]) = {
import c.universe._
val Literal(Constant(lit: String)) = name.tree
val anon = newTypeName(c.fresh)
c.Expr(Block(
ClassDef(
Modifiers(Flag.FINAL), anon, Nil, Template(
Nil, emptyValDef, List(
constructor(c.universe),
DefDef(
Modifiers(), newTermName(lit), Nil, Nil, TypeTree(),
c.literal(42).tree
)
)
)
),
Apply(Select(New(Ident(anon)), nme.CONSTRUCTOR), Nil)
))
}
우리는 그것을 밖으로 시도 할 때, 우리는 구조 유형을하지 않습니다
scala> MacroExample.bar("test")
res1: AnyRef = $1$$1@da12492
그러나 우리가 거기에 여분의 익명 클래스 스틱 경우 :
def baz(name: String): Any = macro baz_impl
def baz_impl(c: Context)(name: c.Expr[String]) = {
import c.universe._
val Literal(Constant(lit: String)) = name.tree
val anon = newTypeName(c.fresh)
val wrapper = newTypeName(c.fresh)
c.Expr(Block(
ClassDef(
Modifiers(), anon, Nil, Template(
Nil, emptyValDef, List(
constructor(c.universe),
DefDef(
Modifiers(), newTermName(lit), Nil, Nil, TypeTree(),
c.literal(42).tree
)
)
)
),
ClassDef(
Modifiers(Flag.FINAL), wrapper, Nil,
Template(Ident(anon) :: Nil, emptyValDef, constructor(c.universe) :: Nil)
),
Apply(Select(New(Ident(wrapper)), nme.CONSTRUCTOR), Nil)
))
}
그것은 작동 :
scala> MacroExample.baz("test")
res0: AnyRef{def test: Int} = $2$$1@6663f834
scala> res0.test
res1: Int = 42
이것은 매우 편리합니다 - 그것은 당신을 위해이 같은 일을 예를-하지만 작동 왜 이해가 안 할 수 있으며, 형식 멤버 버전 작동하지만 바 없습니다. 나는이 알고 동작을 정의 할 수 없습니다 수 있지만, 그것은 어떤 의미가 있습니까? 매크로에서 (그것의 방법과) 구조 유형을 얻을 수있는 청소기 방법이 있나요?
해결법
-
==============================
1.이 질문은 여기 트래비스에 의해 이중으로 대답한다. (코멘트와 메일 링리스트) 추적기와 유진의 토론에 대한 문제에 대한 링크가 있습니다.
이 질문은 여기 트래비스에 의해 이중으로 대답한다. (코멘트와 메일 링리스트) 추적기와 유진의 토론에 대한 문제에 대한 링크가 있습니다.
유형 검사의 유명한 "스킬라와 디즈"섹션에서, 우리의 영웅은 어두운 익명 성을 탈출 및 구조 유형의 구성원으로 빛을 보게 될 것을 결정한다.
(양 포옹의 오디세우스의 계략을 수반하지 않는) 유형 검사를 속일 수있는 방법이 몇 가지 있습니다. 간단한 익명 클래스가 인스턴스화 다음과 같은 블록이 보이지 않도록 더미 문을 삽입하는 것입니다.
당신이 외부에서 참조되지 않는 공공 용어있어하는 TYPER 통지하는 경우, 그것은 당신이 개인 만들 것입니다.
object Mac { import scala.language.experimental.macros import scala.reflect.macros.Context /* Make an instance of a structural type with the named member. */ def bar(name: String): Any = macro bar_impl def bar_impl(c: Context)(name: c.Expr[String]) = { import c.universe._ val anon = TypeName(c.freshName) // next week, val q"${s: String}" = name.tree val Literal(Constant(s: String)) = name.tree val A = TermName(s) val dmmy = TermName(c.freshName) val tree = q""" class $anon { def $A(i: Int): Int = 2 * i } val $dmmy = 0 new $anon """ // other ploys //(new $anon).asInstanceOf[{ def $A(i: Int): Int }] // reference the member //val res = new $anon //val $dmmy = res.$A _ //res // the canonical ploy //new $anon { } // braces required c.Expr(tree) } }
from https://stackoverflow.com/questions/14370842/getting-a-structural-type-with-an-anonymous-classs-methods-from-a-macro by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 어떻게 스칼라 또는 Java에서 혼합 된 인코딩 된 텍스트 파일을 읽을 수? (0) | 2019.11.25 |
---|---|
[SCALA] 스칼라의 byte 배열로 파일을 읽는 방법 (0) | 2019.11.25 |
[SCALA] 어떻게지도 [지능은 모든,] 스칼라에서의 SortedMap로 변환합니까? 아니면 TreeMap의? (0) | 2019.11.25 |
[SCALA] 이클립스는 SBT에서 종속성을 인식해야하는 방법 (0) | 2019.11.25 |
[SCALA] 멀티 프로젝트에서 SBT 테스트 - 종속 관계 : 종속 프로젝트에 테스트 - 코드 사용 가능 확인 (0) | 2019.11.25 |