As we know, it is easy to create an inner class in some methods with scala macro.
But I'd like to know is it possible to generate a top level class/object?
If the answer is yes, then how to avoid generate the same class twice?
my scala version is 2.11
Top-level expansions must retain the number of annottees, their flavors and their names, with the only exception that a class might expand into a same-named class plus a same-named module, in which case they automatically become companions as per previous rule.
https://docs.scala-lang.org/overviews/macros/annotations.html
So you can transform top-level
#annot
class A
into
class A
object A
or
#annot
object A
into
class A
object A
Also there existed c.introduceTopLevel but it was removed.
Context.introduceTopLevel. The Context.introduceTopLevel API, which used to be available in early milestone builds of Scala 2.11.0 as a stepping stone towards type macros, was removed from the final release, because type macros were rejected for including in Scala and discontinued in macro paradise.
https://docs.scala-lang.org/overviews/macros/changelog211.html
Scala Macro: Define Top Level Object
introduceTopLevel has provided a long-requested functionality of generating definitions that can be used outside macro expansions. However, metaprogrammers have
quickly discovered that introduceTopLevel is dangerous. Top-level scope is a resource shared between the typechecker and user metaprograms, so mutating it with
introduceTopLevel can lead to compilation order problems. For example, if one file
in a compilation run relies on definitions created by a macro expansion performed in
another file, compiling the former before the latter may lead to unexpected compilation
errors.
https://infoscience.epfl.ch/record/226166/files/EPFL_TH7159.pdf (section 5.2.3 Conclusion)
If the companion you want to generate already exists then the companion you return in macro annotation's macroTransform will replace the original. You don't need to beware that there will be two "companions", compiler will watch that. But surely normally you match if that's the case (whether there is only annottee or annottee + companion).
Related
I am very new at Scala and Spark area, and I found a strange grammar usage in the scala inside the Apache beam project and I can't understand.
Here is the strange place:
JavaDStream<Metadata> metadataDStream = mapWithStateDStream.map(new Tuple2MetadataFunction());
// register ReadReportDStream to report information related to this read.
new ReadReportDStream(metadataDStream.dstream(), id, getSourceName(source, id), stepName)
.register();
From the above code, you can see inside the constructor of ReadReportDstream, the first parameter is
metadataDStream.dstream()
If we go inside the dstream() method, you will see the following code:
class JavaDStream[T](val dstream: DStream[T])(implicit val classTag: ClassTag[T])
extends AbstractJavaDStreamLike[T, JavaDStream[T], JavaRDD[T]] {
I am wondering why it uses "metadataDStream.dstream()" in the constructor instead of "metadataDStream.dstream"? What does the "()" do?
It's mostly a question of convention. Methods with empty parameter lists are evaluated for their side-effects. Methods without parameters are assumed to be purely functional, and free of side-effects. You can read more about that here - https://docs.scala-lang.org/style/method-invocation.html (Arity-0 section)
So in that case, we're probably having some side-effects in metadataDStream.dstream(). However, syntactically writing it as metadataDStream.dstream won't be an error.
The Scala reflection is really complicated. It contains type symbol and mirror. Could you tell me the relationship between them?
When working with the Scala Reflection API you encounter a lot more types that what you're used to if you've used the Java Reflection API. Given an example scenario where you start with a String containing a fully qualified class name of a class, these are the types you are likely to encounter:
Universe: Scala supports both runtime and compile time reflection. You choose what kind of reflection you're doing by importing from the corresponding universe. For runtime reflection, this corresponds to the scala.reflect.runtime package, for compile time reflection it corresponds to the scala.reflect.macros package. This answer focus on the former.
Like Java you typically start any reflection by choosing which ClassLoader's classes you want to reflect on. Scala provides a shortcut for using the ClassLoader of the current class: scala.reflect.runtime.currentMirror, this gives you a Mirror (more on mirrors later). Many JVM applications use just a single class loader, so this is a common entry point for the Scala Reflection API. Since you're importing from runtime you're now in that Universe.
Symbols: Symbols contain static metadata about whatever you want to reflect. This includes anything you can think of: is this thing a case class, is it a field, is it a class, what are the type parameters, is it abstract, etc. You may not query anything that might depend on the current lexical scope, for example what members a class has. You may also not interact with the thing you reflect on in any way (like accessing fields or calling methods). You can just query metadata.
Lexical scope is everything you can "see" at the place you're doing reflection, excluding implicit scope (see this SO for a treatment of different scopes). How can members of a class vary with lexical scope? Imagine an abstract class with a single def foo: String. The name foo might be bound to a def in one context (giving you a MethodSymbol should you query for it) or it could be bound to a val in another context (giving you a TermSymbol). When working with Symbols it's common to explicitly have to state what kind of symbol you expect, you do this through the methods .asTerm, .asMethod, .asClass etc.
Continuing the String example we started with. You use the Mirror to derive a ClassSymbol describing the class: currentMirror.staticClass(myString).
Types: Types lets you query information about the type the symbol refers to in the current lexical context. You typically use Types for two things: querying what vars, vals and defs there are, and querying type relationships (e.g. is this type a subclass of that type). There are two ways of getting hold of a Type. Either through a TypeSymbol (ClassSymbol is a TypeSymbol) or through a TypeTag.
Continuing the example you would invoke the .toType method on the symbol you got to get the Type.
Scopes: When you ask a Type for .members or .decl—this is what gives you terms (vars and vals) and methods—you get a list of Symbols of the members in the current lexical scope. This list is kept in a type MemberScope, it's just a glorified List[Symbol].
In our example with the abstract class above, this list would contain a TermSymbol or a MethodSymbol for the name foo depending on the current scope.
Names: Names come in two flavors: TermName and TypeName. It's just a wrapper of a String. You can use the type to determine what is named by any Name.
Mirrors: Finally mirrors are what you use to interact with "something". You typically start out with a Symbol and then use that symbol to derive symbols for the methods, constructors or fields you want to interact with. When you have the symbols you need, you use currentMirror to create mirrors for those symbols. Mirrors lets you call constructors (ClassMirror), access fields (FieldMirror) or invoke methods (MethodMirror). You may not use mirrors to query metadata about the thing being reflected.
So putting an example together reflecting the description above, this is how you would search for fields, invoke constructors and read a val, given a String with the fully qualified class name:
// Do runtime reflection on classes loaded by current ClassLoader
val currentMirror: universe.Mirror = scala.reflect.runtime.currentMirror
// Use symbols to navigate to pick out the methods and fields we want to invoke
// Notice explicit symbol casting with the `.as*` methods.
val classSymbol: universe.ClassSymbol = currentMirror.staticClass("com.example.Foo")
val constructorSymbol: universe.MethodSymbol = classSymbol.primaryConstructor.asMethod
val fooSymbol: Option[universe.TermSymbol] = classSymbol.toType.members.find(_.name.toString == "foo").map(_.asTerm)
// Get mirrors for performing constructor and field invocations
val classMirror: universe.ClassMirror = currentMirror.reflectClass(classSymbol)
val fooInstance: Foo = classMirror.reflectConstructor(constructorSymbol).apply().asInstanceOf[Foo]
val instanceMirror: universe.InstanceMirror = currentMirror.reflect(fooInstance)
// Do the actual invocation
val fooValue: String = instanceMirror.reflectField(fooSymbol.get).get.asInstanceOf[String]
println(fooValue) // Prints the value of the val "foo" of the object "fooInstance"
So I'm playing with writing a battlecode player in Scala. In battlecode certain classes are disallowed and there is a runtime exception if you ever try to access them. When I use the Array.fill function I get a message from the battlecode server saying [java] Illegal class: scala/reflect/Manifest$. This is the offending line:
val g_score = Array.fill[Int](rc.getMapWidth(), rc.getMapHeight())(0)
The method takes an implicit ClassManifest argument which has the following documentation:
A ClassManifest[T] is an opaque descriptor for type T. It is used by the compiler
to preserve information necessary for instantiating Arrays in those cases where
the element type is unknown at compile time.
But I do know the type of the array elements at compile time, as shown above I explicitly state that they will be Int. Is there a way to avoid this? To workaround I've written my own version of Array.fill. This seems like a hack. As an aside, does Scala have real 2D arrays? Array.fill seems to return an Array[Array[T]] which is the only way I found to write my own. This also seems inelegant.
Edit: Using Scala 2.9.1
For background information, see this related question: What is a Manifest in Scala and when do you need it?. In this answer, you will find an explanation why manifests are needed for arrays.
In short: Although the JVM uses type erasure, arrays are an exception and need a manifest. Since you could compile your code, that manifest was found (manifests are always available for proper types). Your error occurs at runtime.
I don't know the details of the battlecode server, but there are two possibilities: Either you are running your compiled classes with a binary incompatible version of Scala (difference in major version, e.g. compiled with Scala 2.9 and server uses 2.10). Or the server doesn't even have the scala-library.jar on its class path.
As said in the comment, manifests are deprecated in Scala 2.10 and replaced by ClassTag.
EDIT: So it seems the class loader is artificially restricting the allowed classes. My suggestion would be: Add a helper Java class. You can easily mix Java and Scala code. If it's just about the Int-Array instantiation, you could provide something like:
public static class Helper {
public static int[][] makeArray(int d1, int d2) { return new int[d1][d2](); }
}
(hope that's valid java code, a bit rusty)
Also, have you tried to create the outer array with new Array[Array[Int]](d1), and then iterate to create the inner arrays?
Special means that they give you functionality which is impossible to get otherwise, so they treat by compiler in special way.
Examples: 'DelayedInit' - convert all init code to main methods, 'Dynamic' - proxy of all methods etc
At present, the only special traits I'm aware of are DelayedInit and Dynamic.
Anything inheriting from these traits also gets special treatment by the compiler, as with App, which subclasses DelayedInit.
It's worth noting that any trait could potentially be used as a marker by some library, framework, or compiler plugin to "give you functionality which is impossible to get otherwise". These two are the only traits that are specially recognized by the default compiler though.
As well as marker traits, there are some annotations that get treated specially, the scala.annotation and scala.reflect are good places to find these, there's also the #specialized annotation in the scala package and several in compiler plugins (such as delimited continuations).
There is also scala.Singleton.
It is a final trait and cannot be used normally while writing code, but everyone using some a singleton like object Foo has already used it indirectly.
Singleton is used by the compiler to extend a singleton, therefore:
scala> object Foo
defined module Foo
scala> Foo.isInstanceOf[Singleton]
res0: Boolean = true
I just read and enjoyed the Cake pattern article. However, to my mind, one of the key reasons to use dependency injection is that you can vary the components being used by either an XML file or command-line arguments.
How is that aspect of DI handled with the Cake pattern? The examples I've seen all involve mixing traits in statically.
Since mixing in traits is done statically in Scala, if you want to vary the traits mixed in to an object, create different objects based on some condition.
Let's take a canonical cake pattern example. Your modules are defined as traits, and your application is constructed as a simple Object with a bunch of functionality mixed in
val application =
new Object
extends Communications
with Parsing
with Persistence
with Logging
with ProductionDataSource
application.startup
Now all of those modules have nice self-type declarations which define their inter-module dependencies, so that line only compiles if your all inter-module dependencies exist, are unique, and well-typed. In particular, the Persistence module has a self-type which says that anything implementing Persistence must also implement DataSource, an abstract module trait. Since ProductionDataSource inherits from DataSource, everything's great, and that application construction line compiles.
But what if you want to use a different DataSource, pointing at some local database for testing purposes? Assume further that you can't just reuse ProductionDataSource with different configuration parameters, loaded from some properties file. What you would do in that case is define a new trait TestDataSource which extends DataSource, and mix it in instead. You could even do so dynamically based on a command line flag.
val application = if (test)
new Object
extends Communications
with Parsing
with Persistence
with Logging
with TestDataSource
else
new Object
extends Communications
with Parsing
with Persistence
with Logging
with ProductionDataSource
application.startup
Now that looks a bit more verbose than we would like, particularly if your application needs to vary its construction on multiple axes. On the plus side, you usually you only have one chunk of conditional construction logic like that in an application (or at worst once per identifiable component lifecycle), so at least the pain is minimized and fenced off from the rest of your logic.
Scala is also a script language. So your configuration XML can be a Scala script. It is type-safe and not-a-different-language.
Simply look at startup:
scala -cp first.jar:second.jar startupScript.scala
is not so different than:
java -cp first.jar:second.jar com.example.MyMainClass context.xml
You can always use DI, but you have one more tool.
The short answer is that Scala doesn't currently have any built-in support for dynamic mixins.
I am working on the autoproxy-plugin to support this, although it's currently on hold until the 2.9 release, when the compiler will have new features making it a much easier task.
In the meantime, the best way to achieve almost exactly the same functionality is by implementing your dynamically added behavior as a wrapper class, then adding an implicit conversion back to the wrapped member.
Until the AutoProxy plugin becomes available, one way to achieve the effect is to use delegation:
trait Module {
def foo: Int
}
trait DelegatedModule extends Module {
var delegate: Module = _
def foo = delegate.foo
}
class Impl extends Module {
def foo = 1
}
// later
val composed: Module with ... with ... = new DelegatedModule with ... with ...
composed.delegate = choose() // choose is linear in the number of `Module` implementations
But beware, the downside of this is that it's more verbose, and you have to be careful about the initialization order if you use vars inside a trait. Another downside is that if there are path dependent types within Module above, you won't be able to use delegation that easily.
But if there is a large number of different implementations that can be varied, it will probably cost you less code than listing cases with all possible combinations.
Lift has something along those lines built in. It's mostly in scala code, but you have some runtime control. http://www.assembla.com/wiki/show/liftweb/Dependency_Injection