Assign single element to an IntArray value attribute in Kotlin annotations - annotations

I have a custom annotation declared as
#Target(AnnotationTarget.FUNCTION)
annotation class Anno(val value: IntArray, val attr2: Int = 0)
For a single element declaration, I'm able to use the above annotation in a Java class as
#Anno(1)
but while writing the same in a Kotlin class, I have to put enclosing brackets
#Anno([1])
Aren't the brackets unnecessary in this case or am I declaring the annotation wrong? I am using Kotlin version 1.2.0-rc-39

Yes, square brackets (Kotlin 1.2+) or arrayOf (Kotlin 1.2-) are required.
But as long as this is your annotation, written in Kotlin, you can do fancy things with it, like taking lambdas or varargs, so you can try to tune the resulting syntax for your need. For example, this will be valid syntax, even in Kotlin 1.2-:
#Target(AnnotationTarget.FUNCTION)
annotation class Anno(
val attribute: String,
vararg val value: Int
)
#Anno("test", 1, 2, 3)
fun test() = 42
You'll need to put vararg parameter at the end.

Related

Add ArrayBuffer Element via def in Scala

I am curious as to how to add an ArrayBuffer element via a def. E.g.
def addToArray[T](data: ArrayBuffer[T]): ArrayBuffer[T] = {
return(data += T("XYZ"))
}
I tried this but no go. I assume we cannot do this generically, but I would like to know how to do this. If I do this, return(new ArrayBuffer[T]()), it works. Not the most difficult but somehow escaping me.
Just give the def your generic buffer and the element you want to add then return it:
def addToArrayBuffer[T](data: ArrayBuffer[T], elem: T): ArrayBuffer[T] = {
data += elem
data
}
println(addToArrayBuffer(ArrayBuffer(1, 2, 30), 4)) // ArrayBuffer(1, 2, 30, 4)
If you are not passing the element you want to add as a parameter to the def, then you can't add it inside the def. The idea is that you cannot create an instance of a type parameter, because instantiation requires a constructor which is unavailable if the type is unknown. This restriction is mentioned in the Java generics spec here:
Cannot Create Instances of Type Parameters: You cannot create an
instance of a type parameter. For example, the following code causes a
compile-time error:
public static <E> void append(List<E> list) {
E elem = new E(); // compile-time error
list.add(elem);
}
Wikipedia also explains this very nicely:
Java generics differ from C++ templates. Java generics generate only
one compiled version of a generic class or function regardless of the
number of parameterizing types used. Furthermore, the Java run-time
environment does not need to know which parameterized type is used
because the type information is validated at compile-time and is not
included in the compiled code. Consequently, instantiating a Java
class of a parameterized type is impossible because instantiation
requires a call to a constructor, which is unavailable if the type is
unknown.
Note that there might be a workaround to this using reflection, which is further detailed in the spec.

Why can't I call the Scala Seq.empty[Int]() method?

I'm trying to create a class with an attribute named _1d_matrix, which is a 1D matrix. I would want to fill it with 0.
Thus, I tried to call the method empty of the Seq object (of course not the trait), as mentionned in the documentation : http://www.scala-lang.org/api/2.12.3/scala/collection/Seq$.html#empty[A]:CC[A]
For the moment my code is :
class Calc(val width : Int) {
private val _1d_matrix : Seq.empty[Int]()
}
But there are three errors :
empty is undefined
() can't be written (2 errors : "; or newline is expected" + "definition or declaration is expected")
I think it's because it's not allowed to directly make use of Seq instead of List (e.g.). But : why ? After all, Seq is an object (and a trait but not in my code).
Right way to initialize field looks like this:
private val _1d_matrix = Seq.empty[Int]
or
private val _1d_matrix: Seq[Int] = Seq()
There are two ways to define a 0-arity (no arguments) method in scala - with a pair of parenthesis after the name def exit(), and without one: def empty.
When it is defined in the former way, you can call it with or without parenthesis: exit() or exit - both work. But when parenthesis are not included into the method definition, you can not have them at the call site either: Seq.empty[Int] works, but Seq.empty[Int]() does not.
The convention is to use parenthesis for functions that have side effects, and not use them for purely functional calls.
The other problem with your code is that you have a : where it needs to be an assignment.
So, something like this should work:
val _1d_matrix = Seq.empty[Int]
Your thinking is correct but you have a couple syntax errors.
private val _1d_matrix : Seq.empty[Int]()
: here is used to define a type annotation, so it's trying to find the type Seq.empty rather than the method. That fails because there is no such type.
Use = instead to assign a value. Adding the type here is optional since Scala is able to infer the correct type.
The other is that the empty method is defined without parens, so you must use Seq.empty[Int] instead of Seq.empty[Int]()

Is it possible to create a secondary constructor without a macro annotation in Scala?

I would like to create a macro that generates a secondary constructor{'s body). Is it possible to do this without resorting to macro annotations? (i.e. macro-paradise plugin)
For example:
Something like this:
class A(a : String, b : String) {
def this(s : List[Any]) = macro fromlist
}
Should be equivalent to something like this:
class A(a : String, b : String) {
def this(s : List[Any]) = this(s.head.toString, s.tail.head.toString)
}
Simply using the "macro" keyword does not seem to help. Is this completely disallowed in plain Scala? Thanks.
The problem is, that a constructor is not a method returning a new instance, but a method initializing an already created one. (So the = in your constructor definition does not make sense, the parent constructor does not return anything).
The next problem is, that an alternative constructor in Scala has to call an other constructor as the first step, you cannot call something else, not even a macro.
You could however call a macro to generate the parameters to this, like
this(fromList(s): _*)
But why would you even want to do that? It is very uncommon in Scala to have multiple constructors. The common way is to have an overloaded apply method in the companion object. You don't have any restrictions there.

Scala class that handles enumerations generically

I want to create a generic class that holds the value of an enumeration, and also allows access to the possible values of the enumeration. Think of a property editor for example - you need to know the current value of the property, and you also need to be able to know what other values are legal for the property. And the type of enumeration should not be known in advance, you should be able to work with any kind of enumeration.
My first thought was something like this:
class EnumerationProperty[T <: Enumeration](value:T)
However, that doesn't work because for enumerations T isn't a type, it's an object. Other variations I have tried are:
class EnumerationProperty[T <: Enumeration](value:T.Value)
class EnumerationProperty[T <: Enumeration.Value](value:T)
(I won't go into the details of why these don't work because I suspect the reasons aren't interesting.)
For first part of your question. You can define holder for generic enum value like this:
case class EnumerationProperty[T <: Enumeration#Value](value:T)
But I don't know how to get all enum values without explicitly pass Enumeration object. Enumeration has values() method to get all values. And Enumeration#Value has link to Enumeration, but with private access
In your use case (a property editor) I think the best solution is to rely on scala reflection available in scala 2.10. Given a class's TypeTag, you can get the full type (without erasure) of all of its members plus their values, and from that populate your property editor. For enumerations, use the TypeTag to get their values using the following method:
Using Scala 2.10 reflection how can I list the values of Enumeration?
Now, maybe you don't want or can't use scala reflection, and from now on I'll suppose this is the case. If that is true then you are opening a whole can of worm :)
TL;DR: This is not possible using a standard Enumeration, so you'll probably have to explcitly wrap the enumeration values as shown in Ptharien's Flame's answer (or roll your own fork of Enumeration). Below I detail all my attempts, please bear with me.
Unfortunately, and for some unknown reason to me (though I suspect it has to do with serialization issues), Enumeration.Value has no field pointing to its Enumeration instance. Given how Enumeration is implemented, this would be trivial to implement, but of course wehave no say, short of forking Enumeration and modifying our version (which is actually what I did for this very purpose, plus to add proper support for serialization and reflection - but I diggress).
If we can't modify Enumeration, maybe we can just extend it? Looking at the implementation again, something like this would seem to work:
class EnumerationEx extends Enumeration {
protected class ValEx(i: Int, name: String) extends Val(i, name) {
#transient val enum: Enumeration = EnumerationEx.this
}
override protected def Value(i: Int, name: String): Value = new ValEx(i, name)
}
object Colors extends EnumerationEx {
val Red, Green, Blue = Value
}
The downside would be that it only works for enumerations that explicitly extend EnumerationEx instead of Enumeration, but it would be better than nothing.
Unfortunately, this does not compile simply because def Value ... is declared final in Enumeration so there is no way to override it. (Note again that forking Enumeration would allow to circunvent this. Actually, why not do it, as we are already down the path of using a custom Enumeration anwyay. I'll let you judge).
So here is another take on it:
class EnumerationEx extends Enumeration {
class ValueWithEnum( inner: Value ) {
#transient val enum: Enumeration = EnumerationEx.this
}
implicit def valueToValue( value: Value ): ValueWithEnum = new ValueWithEnum( value )
}
And indeed it works as expected. Or so it seems.
scala> object Colors extends EnumerationEx {
| val Red, Green, Blue = Value
| }
defined module Colors
scala> val red = Colors.Red
red: Colors.Value = Red
scala> red.enum.values
res58: Enumeration#ValueSet = Colors.ValueSet(Red, Green, Blue)
Hooray? Well no, because the conversion from Value to ValueWithEnum is done only when accessing red.enum, not at the time of instantiation of the Colors enumeration. In other words, when calling enum the compiler needs to know the exact static type of the enumeration (the compiler must statically know that red's type is Colors.Value, and not just Enumeration# Value). And in the use case you mention (a property editor) you can only rely to java reflection (I already assumed that you won't use scala reflection) to get the type of an enumeration value, and java reflection will only give you Enumeration#Val (which extends Enumeration#Value) as the type of Colors.Red. So basically you are stuck here.
Your best bet is definitly to use scala reflection in the first place.
class EnumProps[E <: Enumeration](val e: E)(init: e.Value) {...}
Then you can use e and e.Value to implement the class.

How should Scala default arguments to refer to a previous positional argument?

Scala-lang reference 5.5.1 and 6.6.1 gave me the impression that a default parameter would be able to refer to a previously evaluated one:
class Test(val first: String, val second: String = first)
but from experimenting it seems the only way to do this is to use the form:
class Test(val first: String)(val second: String = first)
and then define an auxiliary constructor or a creational companion class to avoid specifying the second set of brackets when creating. I don't really understand how this second constructor works, it looks like a curried function so I might guess that it is necessary to evaluate first independently of second, is this correct? Is this form necessary or is there some syntatic sugar I can use to tweak the first constructor into doing what I want?
As Travis Brown points out, you can indeed only refer to a previous argument in a default expression when it is from a previous argument list (so you do need to currify).
Now, regarding your particular use case, default arguments and method overloading are sometimes two ways of achieving the same thing.
I think the simplest solution to your scenario is simply to define Test as follows:
class Test(val first : String, val second : String) {
def this(f : String) = this(f, f)
}
If you want to make it more complicated, an alternative way, using a companion object:
class Test(val first : String)(val second : String = first)
object Test {
def apply(f : String) = new Test(f)
def apply(f : String, s : String) = new Test(f)(s)
}
(A small difference is that now you create objects without new.)
What you cannot do, is define it as:
class Test(val first : String)(val second : String = first) {
def this(f : String, s : String) = this(f)(s)
}
...because the curried version gets translated into (among other things) a method with the same signature as the overloaded contructor.
From 5.3 of the spec:
The scope of a formal value parameter includes all subsequent
parameter sections and the template t.
Regular methods are the same, by the way (from 4.6):
The scope of a formal value parameter name x comprises all
subsequent parameter clauses, as well as the method return type and
the function body, if they are given.
I.e., whether you've got a constructor or an ordinary method, a value parameter name isn't in scope in its own parameter clause. In your second version the constructor has two parameter clauses, and first is only in scope in the second. See 5.3 for more detail about multiple parameter clauses.