I would like to create a macro generated hierarchy of sealed abstract and case classes. There was an example similar to this with http://docs.scala-lang.org/overviews/macros/typemacros.html but is is now obsolete. Is this still possible?
I think it would be incredibly powerful to generate a type safe AST for some specified grammar. Ideally with an IDE able to resolve all the classes.
First for some shameless self-promotion: Eugene Burmako and I are giving a talk on type providers, a closely related topic, at Scalar 2014 tomorrow, and I encourage you to take a look at the example project we put together for the talk if you're interested in this kind of thing.
While type macros are no longer supported, you can accomplish essentially the same thing with macro annotations from macro paradise (which is available as a plugin for Scala 2.10 and 2.11):
import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.Context
// Add constructor arguments here.
class expand extends StaticAnnotation {
def macroTransform(annottees: Any*) = macro Expander.expand_impl
}
object Expander {
def expand_impl(c: Context)(annottees: c.Expr[Any]*) = {
import c.universe._
annottees.map(_.tree) match {
case List(q"trait $name") => c.Expr[Any](
// Add your own logic here, possibly using arguments on the annotation.
q"""
sealed trait $name
case class Foo(i: Int) extends $name
case class Bar(s: String) extends $name
case object Baz extends $name
"""
)
// Add validation and error handling here.
}
}
}
And then:
scala> #expand trait MyADT
defined trait MyADT
defined class Foo
defined class Bar
defined module Baz
You can add arguments to the annotation that will be available at compile time, allowing you to parse an external resource that you can use to generate the implementation of the ADT, for example.
Macro annotations are very experimental and their status is still up in the air—there's no guarantee that they'll ship with Scala 2.12, for example. Something similar (although not quite so clean) is possible using plain old def macros and structural types—see the example project linked above for more detail and some demonstrations. In any case, this kind of mechanism is of interest to many people, including the developers of Scala's macro system, so even if macro annotations disappear at some point down the road, there's likely to be some way to accomplish what you've described here.
Related
When using a macro to materialize an implementation of a trait, I'd like to create the implementation within a package so that it has access to other package-private classes.
trait MyTrait[T]
object MyTrait {
implicit def materialize[T]: MyTrait[T] = macro materializeImpl[T]
def materializeImpl[T : c.WeakTypeTag](c: blackbox.Context): c.Expr[MyTrait[T]] = {
val tt = weakTypeTag[T]
c.Expr[MyTrait[T]](q"new MyTrait[$tt] {}")
}
}
Is it possible to materialize new MyTrait[$tt] {} within a particular package?
A macro has to expand into an AST which would compile in the place the macro call is in. Since package declarations are only allowed at top-level, and method calls aren't allowed there, the expanded tree can't create anything in another package.
As Alexey Romanov pointed out this is not possible directly. Still if you call only a few methods (and if you use macro, most probably this is so), one possible (but not perfect) workaround might be creating a public abstract class or trait that extends the target trait and "publishes" all the required package private methods as protected proxies. So you can create instances in your macro from inheriting from that abstract class rather than trait. Obviously this trick effectively "leaks" those methods to anyone but thanks to reflection anyone can call any method if he really wants. And abusing this trick will show as deliberate effort to circumvent your separation as the usage of the reflection.
I'll get straight to the business.
Let's say that I have the following trait definition:
trait Routable{
def routing(): String
}
And I'm defining the following class:
case class MyEvent(name: String, age: Int) extends Routable{
override def routing(): String = "this is my routing key"
}
I'm trying to make a macro called routeOf[MyEvent] to return the routing key of the defined class.
I tried so many things for the last 3 days and I'm starting to wonder if it is possible at all...
My macro definition is:
def routeOf[T]: Any = macro RouteOfMacro.impl[T]
def impl[T: c.WeakTypeTag](c: whitebox.Context): c.Tree
But I can't find how to extract the method from the WeakTypeTag (and the internet is not full with examples).
So can it be done?
I'm trying to make a macro called routeOf[MyEvent] to return the
routing key of the defined class.
The way your code is, it's not the routing key of the defined class, but of the instance.
If you create multiple MyEvent, there is no guarantee their routing keys would be alike.
What you can do is create a companion object MyEvent that derives from Routable. I feel classTag or typeTag may be enough for this case - do you know those? No macros should be needed. But until I know the larger picture, hard to say how I'd approach it. Can you reveal more? :)
Part I
Suppose I have a type class trait Show[T] { def print(t: T): String } with instances for String and Int. Suppose I have a value whose specific type is known only at runtime:
val x: Any = ...
How do I get the appropriate typeclass instance (at runtime, since we don't know the type statically) and do something with it.
Note that it's inadequate to define a method that literally just gives us the typeclass instance:
def instance(x: Any): Show[_]
Since Show.print requires statically known argument type T we still can't do anything with the result of instance. So really, we need to be able to dynamically dispatch to an already-defined function that uses the instance, such as the following:
def display[T](t: T)(implicit show: Show[T]) = "show: " + show.print(t) + "\n"
So assuming display is defined, how do we invoke display, passing along an appropriate Show instance. I.e. something that invokes display(x) properly.
Miles Sabin accomplishes this here using runtime compilation (Scala eval), as an example of "staging", but with only spare documentation as to what's going on:
https://github.com/milessabin/shapeless/blob/master/examples/src/main/scala/shapeless/examples/staging.scala
Can Miles's approach be put into a library? Also, what are the limitations of this approach e.g. with respect to generic types like Seq[T]?
Part II
Now suppose T is bounded by a sealed type (such that it's possible to enumerate all the sub-types):
trait Show[T <: Foo]
sealed trait Foo
case class Alpha(..) extends Foo
case class Beta(..) extends Foo
In this case, can we do it with a macro instead of runtime compilation? And can this functionality be provided in some library?
I mostly care about Scala 2.12, but it's worth mentioning if a solution works in 2.11 or 2.10.
I'm pretty new to Scala and now I'm trying to learn how to write tests in Scalatest. Here is an example they provided with the using custom matchers section:
import org.scalatest._
import matchers._
trait CustomMatchers {
class FileEndsWithExtensionMatcher(expectedExtension: String) extends Matcher[java.io.File] {
def apply(left: java.io.File) = {
val name = left.getName
MatchResult(
name.endsWith(expectedExtension),
s"""File $name did not end with extension "$expectedExtension"""",
s"""File $name ended with extension "$expectedExtension"""""
)
}
}
def endWithExtension(expecedExtension: String) = new FileEndsWithExtensionMatcher(expectedExtension)
}
// Make them easy to import with:
// import CustomMatchers._
object CustomMatchers extends CustomMatchers
I do not quite understand the reason they pu the FileEndsWithExtensionMatcher class into a trait? Why? Is it idiomatic scala way or some? Can't you explain it?
It is just for your convienience.
That is one of many ways to modularize your code and than reuse it in desired suites. You can organize it in packages or objects and it will work either. With this approach it is just easy to mix traits into your tests. What's more it allows you to nicely organize connected matchers.
For example you can create trait with group of matchers for currencies and another trait matching physical units. Next you can mixin one or both traits into your Test.
The purpose here is to "put all the matchers into one place from which you can easily access them in other code". You could put all these traits into a package and import that package. But the link you reference states that "One good way to organize custom matchers is to place them inside one or more traits that you can then mix into the suites that need them". It would work either way. It's just a matter of preference.
As far as I understand, implicit conversions can result in potentially hard to understand code, or code suffering from other problems (perhaps even bugs?), which is why they require explicit enabling in order to be used in code without getting warnings.
However, given that implicit conversions are in big part (if not most of the time) used for wrapping an object with an object of another type, and so are implicit classes—I'd appreciate you correcting me if I'm wrong—, why do the former require the import of scala.language.implicitConversions but the latter do not?
object Main extends App {
implicit class StringFoo(x: String) {
def fooWithImplicitClass(): Unit =
println("foo with implicit class")
}
// => silence.
"asd".fooWithImplicitClass()
/************************/
class Foo(x: String) {
def fooWithImplicitDef(): Unit =
println("foo with implicit def")
}
implicit def string2Foo(x: String) = new Foo(x)
// => warning: implicit conversion method string2Foo should be enabled
"asd".fooWithImplicitDef()
}
Implicit classes effectively only add new methods (or traits), and they are only ever used when these added methods are called (or the implicit class is used explicitly, but this rarely happens in practice). Implicit conversions to existing types, on the other hand, can be invoked with less visibility to the programmer.
IMO, there is no fundamental difference between an implicit class and an implicit conversion as regards the confusion they might potentially incur, thus both should have been warned.
But by defining a class as implicit, it's like explicitly suppressing the warning by telling the compiler that "I'm an adult, I know what I'm doing. THIS CLASS IS INTENDED TO BE USED THIS WAY (possibly as an extension wrapper)." Therefore no warnings will be given since you, as the creator of the class, have made it clear that using implicitly is how this class is supposed to work or how the class is allowed to be used, compiler should certainly trust you.
You can, on the other hand, convert an object to whichever class by using implicit conversion, no matter if the target class is intended to be used implicitly. This is the source of many troubles, and also what Scala is trying to prevent.