It´s most probably a stupid question, I saw an answer already here but seems does not work in my particular case. Here my code
object ProductAdded{
val PRODUCT_NAME:String="productName"
val PRODUCT_PRICE:String="productPrice"
}
class ProductAdded #JsonCreator()(#JsonProperty(PRODUCT_NAME) var productName: String,
#JsonProperty(PRODUCT_PRICE) var productPrice: String) extends Event {
#JsonProperty(PRODUCT_NAME) def getProductName: String = {
productName
}
#JsonProperty(PRODUCT_PRICE) def getProductPrice: String = {
productPrice
}
}
I´m trying to use those constants in the constructor, but when I compile show this error
Error:(12, 49) annotation argument needs to be a constant; found: event.ProductAdded.PRODUCT_NAME
class ProductAdded #JsonCreator()(#JsonProperty(PRODUCT_NAME) var productName: String,
This is a pretty unfortunate error message, I must say, since Scala doesn't actually have a concept named "constant", so how are you supposed to make something a "constant" if you don't even know what it is?
Scala does, however, have a concept of "constant expression" (bold emphasis mine):
6.24 Constant Expressions
Constant expressions are expressions that the Scala compiler can evaluate to a constant. The definition of "constant expression" depends on the platform, but they include at least the expressions of the following forms:
A literal of a value class, such as an integer
A string literal
A class constructed with Predef.classOf
An element of an enumeration from the underlying platform
A literal array, of the form Array(c1, …, cn), where all of the ci's are themselves constant expressions
An identifier defined by a constant value definition.
and "constant value definition" (bold emphasis mine):
A constant value definition is of the form
final val x = e
where e is a constant expression. The final modifier must be present and no type annotation may be given.
So, as you can see, your expression is not a constant value expression, because the definition is not a constant value definition.
In order to turn it into a constant value definition, you need to
remove the type annotation : String
add the final modifier explicitly: even though members of a singleton object are implicitly final, constant value definitions require an explicit annotation
The result would look something like this:
object ProductAdded {
final val PRODUCT_NAME = "productName"
final val PRODUCT_PRICE = "productPrice"
}
class ProductAdded #JsonCreator()(
#JsonProperty(PRODUCT_NAME) var productName: String,
#JsonProperty(PRODUCT_PRICE) var productPrice: String
) extends Event {
#JsonProperty(PRODUCT_NAME) def getProductName = productName
#JsonProperty(PRODUCT_PRICE) def getProductPrice = productPrice
}
Related
I am writing a static analysis using the OPAL framework.
Therefore, I invoke an abstract interpretation of a method, where I have upper type bounds for the passed parameters as FieldTypes.
It looks like this:
BaseAI.perform(classFile, caller, domain)(parameters)
Where parameters is an IndexedSeq[FieldType].
This results in the following type error:
type mismatch; found : scala.collection.immutable.IndexedSeq[org.opalj.br.FieldType] required: Option[scala.collection.IndexedSeq[domain.DomainValue]] (which expands to) Option[scala.collection.IndexedSeq[domain.Value]]
Is there any possibility to convert my FieldTypes to DomainValues?
Can I use
domain.ClassValue(origin, identifiedFieldType)
to convert it, even if the type is e.g. an int? (since int is not a class)
If yes, is there a method, which computes the origin index for method parameters?
Part one of the question:
You can use:
domain.TypedValue(origin, parameterType)
In this case parameterType can be "any type".
Part two of the question:
The following function defined by the package object org.opalj.ai can be used compute the correct value index.
def parameterToValueIndex(
isStaticMethod: Boolean,
descriptor: MethodDescriptor,
parameterIndex: Int
): Int = {
Excuse the long set-up. This question relates to, but is not answered by, Scala: ambiguous reference to overloaded definition - best disambiguation? .
I'm pretty new to Scala, and one thing that's throwing me off is that Scala both:
Has first-class functions
Calls functions when using object-dot notation without any parenthetical argument lists (as if the function were a property)
These two language features are confusing me. Look at the below code:
class MyClass {
def something(in: String): String = {
in + "_X"
}
def something: String => String = {
case _ => "Fixed"
}
}
val my = new MyClass()
println(List("foo", "bar").map(my.something))
I would expect this to print List("foo_X", "bar_X") by calling the something prototype that matches the map's required String => ? argument. Instead, the output is List("Fixed", "Fixed") - Scala 2.11 is invoking the no-argument something() and then passing its return value to the map.
If we comment out the second no-argument prototype of something, the output changes to be the expected result, demonstrating that the other prototype is valid in context.
Adding an empty argument list to the second prototype (making it def something()) also changes the behavior.
Changing the my.something to my.something(_) wakes Scala up to the ambiguity it was silently ignoring before:
error: ambiguous reference to overloaded definition,
both method something in class MyClass of type => String => String
and method something in class MyClass of type (in: String)String
match argument types (String)
println(List("foo", "bar").map(my.something(_)))
Even using the supposedly-for-this-purpose magic trailing underscore doesn't work:
val myFun: (String) => String = my.something _
This results in:
error: type mismatch;
found : () => String => String
required: String => String
val myFun: (String) => String = my.something _
My questions:
If I have MyClass exactly as written (no changes to the prototypes, especially not adding an empty parameter list to one of the prototypes), how do I tell Scala, unambiguously, that I want the first one-argument version of something to pass as an argument to another call?
Since there are clearly two satisfying arguments that could be passed to map, why did the Scala compiler not report the ambiguity as an error?
Is there a way to disable Scala's behavior of (sometimes, not always) treating foo.bar as equivalent to foo.bar()?
I have filed a bug on the Scala issue tracker and the consensus seems to be that this behaviour is a bug. The compiler should have thrown an error about the ambiguous reference to "my.something".
I have trouble in building the following code:
type graph_t = scala.collection.mutable.Map[Long, (Long, Float)];
var graph : graph_t = graph_t();
However, it does work by replacing the graph_t() with the original type:
var graph : graph_t = scala.collection.mutable.Map[Long, (Long, Float)] ();
Any answer will be appreciated.
Scala knows two namespaces: types and values. Types define what values are capable of, and values are the things you call methods on.
graph_t() is a method call (the apply method), but you did not define a value called graph_t, you defined a type called graph_t, and you cannot call methods on types.
The reason scala.collection.mutable.Map[Long, (Long, Float)] () works is because scala.collection.mutable.Map is both a type and a value.
That's interesting. Try this:
type s = String;
var x = s()
You get the same error: not found.
That's is because the name of the class is both the name of the type and the name of the constructor, but the name of a type is not necessarily the name of a constructor.
In this case, the function Map actually constructs a concrete implementation of the Map abstract class.
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.
Consider the following class written in Java:
class NonNegativeDouble {
private final double value;
public NonNegativeDouble(double value) {
this.value = Math.abs(value);
}
public double getValue() { return value; }
}
It defines a final field called value that is initialized in the constructor, by taking its parameter called alike and applying a function to it.
I want to write something similar to it in Scala. At first, I tried:
class NonNegativeDouble(value: Double) {
def value = Math.abs(value)
}
But the compiler complains: error: overloaded method value needs result type
Obviously the compiler thinks that the expression value inside the expression Math.abs(value) refers to the method being defined. Therefore, the method being defined is recursive, so I need to state its return type. So, the code I wrote does not do what I expected it to do: I wanted value inside Math.abs(value) to refer to the constructor parameter value, and not to the method being defined. It is as if the compiler implicitly added a this. to Math.abs(this.value).
Adding val or var (or private ... variants) to the constructor parameter doesn't seem to help.
So, my question is: can I define a property with the same name as a constructor parameter, but maybe a different value? If so, how? If not, why?
Thanks!
No, you can't. In Scala, constructor parameters are properties, so it makes no sense to redefine them.
The solution, naturally, is to use another name:
class NonNegativeDouble(initValue: Double) {
val value = Math.abs(initValue)
}
Used like this, initValue won't be part of the instances created. However, if you use it in a def or a pattern matching declaration, then it becomes a part of every instance of the class.
#Daniel C. Sobral
class NonNegativeDouble(initValue: Double) {
val value = Math.abs(initValue)
}
your code is right, but "constructor parameters are properties",this is not true.
A post from the official site said,
A parameter such as class Foo(x : Int) is turned into a field if it is
referenced in one or more methods
And Martin's reply confirms its truth:
That's all true, but it should be treated as an implementation
technique. That's why the spec is silent about it.
So normally, we can still treat primary constructor parameters as normal method parameter, but when the parameters is referenced by any of the methods, the compiler will cleverly turn it into a private field.
If any formal parameter preceded by the val, the compiler generates an getter definition automatically.if var, generates a setter additionally. see the language speification section 5.3.
That's all about primary constructor parameters.
You can consider parametric field
class NonNegativeDouble(val value: Double, private val name: String ){
if (value < 0) throw new IllegalArgumentException("value cannot be negative")
override def toString =
"NonNegativeDouble(value = %s, name = %s)" format (value, name)
}
val tom = "Tom"
val k = -2.3
val a = new NonNegativeDouble(k.abs, tom)
a: NonNegativeDouble = NonNegativeDouble(value = 2.3, name = Tom)
a.value
res13: Double = 2.3
a.name
<console>:12: error: value name in class NonNegativeDouble cannot be accessed in NonNegativeDouble
a.name
val b = new NonNegativeDouble(k, tom)
java.lang.IllegalArgumentException: value cannot be negative
...
It's defines fields and parameters with the same names "value", "name".
You can add modifiers such as private ...
In the case of case classes it should be:
case class NonNegativeDouble(private val initValue: Double) {
val value = Math.abs(initValue)
def copy(value: Double = this.value) = NonNegativeDouble(value)
}
The implementation of copy is required to prevent the sintesized version of the compiler that will bind the initValue argument.
I expect that the compiler is smart enough to not retain the «extra space» for the initValue. I haven't verified this behaviour.