473,320 Members | 1,987 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Getting a structural type with an anonymous class's methods from a macro ?

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:


Expand|Select|Wrap|Line Numbers
  1. object MacroExample extends ReflectionUtils {
  2.   import scala.language.experimental.macros
  3.   import scala.reflect.macros.Context
  4.  
  5.   def foo(name: String): Any = macro foo_impl
  6.   def foo_impl(c: Context)(name: c.Expr[String]) = {
  7.     import c.universe._
  8.  
  9.     val Literal(Constant(lit: String)) = name.tree
  10.     val anon = newTypeName(c.fresh)
  11.  
  12.     c.Expr(Block(
  13.       ClassDef(
  14.         Modifiers(Flag.FINAL), anon, Nil, Template(
  15.           Nil, emptyValDef, List(
  16.             constructor(c.universe),
  17.             TypeDef(Modifiers(), newTypeName(lit), Nil, TypeTree(typeOf[Int]))
  18.           )
  19.         )
  20.       ),
  21.       Apply(Select(New(Ident(anon)), nme.CONSTRUCTOR), Nil)
  22.     ))
  23.   }
  24. }
(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:

Expand|Select|Wrap|Line Numbers
  1. scala> MacroExample.foo("T")
  2. res0: AnyRef{type T = Int} = $1$$1@7da533f6
Note that it's appropriately typed. We can confirm that everything's working as expected:

Expand|Select|Wrap|Line Numbers
  1. scala> implicitly[res0.T =:= Int]
  2. res1: =:=[res0.T,Int] = <function1>
  3.  
Now suppose that we try to do the same thing with a method:

Expand|Select|Wrap|Line Numbers
  1. def bar(name: String): Any = macro bar_impl
  2. def bar_impl(c: Context)(name: c.Expr[String]) = {
  3.   import c.universe._
  4.  
  5.   val Literal(Constant(lit: String)) = name.tree
  6.   val anon = newTypeName(c.fresh)
  7.  
  8.   c.Expr(Block(
  9.     ClassDef(
  10.       Modifiers(Flag.FINAL), anon, Nil, Template(
  11.         Nil, emptyValDef, List(
  12.           constructor(c.universe),
  13.           DefDef(
  14.             Modifiers(), newTermName(lit), Nil, Nil, TypeTree(),
  15.             c.literal(42).tree
  16.           )
  17.         )
  18.       )
  19.     ),
  20.     Apply(Select(New(Ident(anon)), nme.CONSTRUCTOR), Nil)
  21.   ))
  22. }
But when we try it out, we don't get a structural type

Expand|Select|Wrap|Line Numbers
  1. scala> MacroExample.bar("test")
  2. res1: AnyRef = $1$$1@da12492
But if we stick an extra anonymous class in there:

Expand|Select|Wrap|Line Numbers
  1. def baz(name: String): Any = macro baz_impl
  2. def baz_impl(c: Context)(name: c.Expr[String]) = {
  3.   import c.universe._
  4.  
  5.   val Literal(Constant(lit: String)) = name.tree
  6.   val anon = newTypeName(c.fresh)
  7.   val wrapper = newTypeName(c.fresh)
  8.  
  9.   c.Expr(Block(
  10.     ClassDef(
  11.       Modifiers(), anon, Nil, Template(
  12.         Nil, emptyValDef, List(
  13.           constructor(c.universe),
  14.           DefDef(
  15.             Modifiers(), newTermName(lit), Nil, Nil, TypeTree(),
  16.             c.literal(42).tree
  17.           )
  18.         )
  19.       )
  20.     ),
  21.     ClassDef(
  22.       Modifiers(Flag.FINAL), wrapper, Nil,
  23.       Template(Ident(anon) :: Nil, emptyValDef, constructor(c.universe) :: Nil)
  24.     ),
  25.     Apply(Select(New(Ident(wrapper)), nme.CONSTRUCTOR), Nil)
  26.   ))
  27. }
It works:

Expand|Select|Wrap|Line Numbers
  1. scala> MacroExample.baz("test")
  2. res0: AnyRef{def test: Int} = $2$$1@6663f834
  3.  
  4. scala> res0.test
  5. 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?
Sep 18 '13 #1
0 2209

Sign in to post your reply or Sign up for a free account.

Similar topics

5
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...
5
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......
26
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
1
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 =)
8
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,...
3
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...
7
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 {
16
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...
4
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...
2
DonRayner
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...
0
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...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
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...
0
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...
0
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...
1
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)...
1
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...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
isladogs
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...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.