Suppose we want to write a macro that defines an anonymous class with some type members or methods, and then creates an instance of that class that's statically typed as a structural type with those methods, etc. This is possible with the macro system in 2.10.0, and the type member part is extremely easy: - 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)
-
))
-
}
-
}
(Where ReflectionUtils is a convenience trait that provides my constructor method.)
This macro lets us specify the name of the anonymous class's type member as a string literal: - scala> MacroExample.foo("T")
-
res0: AnyRef{type T = Int} = $1$$1@7da533f6
Note that it's appropriately typed. We can confirm that everything's working as expected: - scala> implicitly[res0.T =:= Int]
-
res1: =:=[res0.T,Int] = <function1>
-
Now suppose that we try to do the same thing with a method: - 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)
-
))
-
}
But when we try it out, we don't get a structural type - scala> MacroExample.bar("test")
-
res1: AnyRef = $1$$1@da12492
But if we stick an extra anonymous class in there: - 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)
-
))
-
}
It works: - scala> MacroExample.baz("test")
-
res0: AnyRef{def test: Int} = $2$$1@6663f834
-
-
scala> res0.test
-
res1: Int = 42
This is extremely handy—it lets you do things like this, for example—but I don't understand why it works, and the type member version works, but not bar. I know this may not be defined behavior, but does it make any sense? Is there an cleaner way to get a structural type (with the methods on it) from a macro?
0 2209 Sign in to post your reply or Sign up for a free account.
Similar topics
by: fotzor |
last post by:
Hi,
is it somehow possible to get the type of a variable in a macro?
example:
#define SOME_MACRO(x) // what's the type of x???
i guess the type-information is lost but i can't use a template...
|
by: bittercold |
last post by:
Hi, guys,
I need to overload global "new" operator but I have to know the type id
"new" is begin invoked on.
For example if I overload it like this
void *operator new(size_t n)
{
...body......
|
by: Michael McGarry |
last post by:
Hi,
I am pretty sure this is not possible, but maybe somehow it is.
Given a variable, can I tell what type it is at runtime?
Michael
|
by: jester |
last post by:
For debugging purposes, I'm trying to programmatically retrieve the user
account name for the anonymous and impersonated account. Using
User.Identity.Name didn't do the trick. Any ideas? Thanks =)
|
by: WakeBdr |
last post by:
I'm writing a class that will query a database for some data and return
the result to the caller. I need to be able to return the result of
the query in several different ways: list, xml,...
|
by: emmaruwa |
last post by:
The following VBA code, in Access 2003, is to make a button open and populate a form based on the Surname and Period_frm data on a previous form. However, i keep getting a type mismatch error...
|
by: David Resnick |
last post by:
I'm faced with a header with anonymous structures declared inside a
union like this:
union msg {
struct {
int a;
int b;
} s1;
struct {
|
by: andreyvul |
last post by:
If I try compiling this in gcc, it says: "error: request for member
`baz' in something not a structure or union".
Any workarounds or tips on how to make a structure such that it
behaves like an...
|
by: philly_bob |
last post by:
In the sample program below, I want to send a random method to a class
instance.
In other words, I don't know which method to send until run-time. How
can I send ch, which is my random choice, to...
|
by: DonRayner |
last post by:
This one has me stumped. I'm getting a "Type Mismatch" error on one of my forms when it's being opened. It's hapening before the forms "On Open" event, I stuck a msgbox in there to check and I'm...
|
by: DolphinDB |
last post by:
Tired of spending countless mintues downsampling your data? Look no further!
In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
|
by: ryjfgjl |
last post by:
ExcelToDatabase: batch import excel into database automatically...
|
by: Vimpel783 |
last post by:
Hello!
Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
|
by: jfyes |
last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
|
by: ArrayDB |
last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
|
by: PapaRatzi |
last post by:
Hello,
I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
|
by: CloudSolutions |
last post by:
Introduction:
For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
|
by: Defcon1945 |
last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
| |