How to get default constructor parameter using reflection? - scala

This kind of seemed easy to figure out but now am confused:
scala> class B(i:Int)
defined class B
scala> classOf[B].getDeclaredFields
res12: Array[java.lang.reflect.Field] = Array()
Note this:
scala> class C(i:Int){
| val j = 3
| val k = -1
| }
defined class C
scala> classOf[C].getDeclaredFields
res15: Array[java.lang.reflect.Field] = Array(private final int C.j, private final int C.k)

If you declare i as a val or a var, or if you make B a case class, then you'll see:
scala> classOf[B].getDeclaredFields
res1: Array[java.lang.reflect.Field] = Array(private final int B.i)
If you do neither, no method or field named i is generated, because it's just a constructor parameter that's never used; there is no reason it would result in a method or field existing.
Note that the Scala compiler never generates public members, only private ones. Access from outside is meant to go through the method named i.

Related

Expression of type list(object) doesn't conform to expected list scala

Supposedly I have the following
case class test {
a:string
b: string
c: Int
d: Int }
var temp = List(test("lol","lel",1,2))
var total = List(test)
total = total:::temp //this doesn't work because temp is of type [test] while total is of type [test.type]
I do not understand the difference.
The reason I want to use this is that I want to have a running list where elements will be conditionally added in a loop.
So in this instance, total should initially an empty list which takes test objects. How do I do this?
Any feedback is appreciated!
Let me begin by explaining few basics about Scala.
In Scala, you define a class like following,
scala> class Demo(a: String, b: Int) {
| def stringify: String = a + " :: " + b
| }
// defined class Demo
You can think of a class as a blueprint given to Scala which will be used to create instances of that class. Here, every instance of class Demo will have two properties - a which will be a String and b which will be an Int and one method - stringify which will return a String.
scala> val demo1 = new Demo("demo1", 1)
// demo1: Demo = Demo#21eee94f
scala> demo1.getClass
// res0: Class[_ <: Demo] = class Demo
Here demo1 is an instance of class Demo and has type Demo.
Scala also has a concept of object which are instances of specially generated inner classes.
scala> object OtherDemo {
| val a: Int = 10
| }
// defined object OtherDemo
scala> DemoObject.getClass
// res2: Class[_ <: OtherDemo.type] = class OtherDemo$
Here OtherDemo will be the only instance of that specially generated class OtherDemo$ and has type OtherDemo.type.
And then there are case class in Scala
scala> case class AnotherDemo(a: Int)
// defined class AnotherDemo
This will create not only a class AnotherDemo but also an object AnotherDemo which we call a companion object. Which is equivalent to,
class AnotherDemo(a: Int)
object AnotherDemo {
def apply(a: Int): AnotherDemo = new AnotherDemo(a)
def unapply(anotherDemo: AnotherDemo): Option[Int] = Some(anotherDemo.a)
// And many more utility functions
}
We call this object AnotherDemo as companion object of class AnotherDemo.
We can create instances of AnotherDemo in two ways,
// By using new keyword, as we can do for any class
scala> val anotherDemo1 = new AnotherDemo(1)
// anotherDemo1: AnotherDemo = AnotherDemo(1)
// Or we can use `apply` method provided by companion object
scala> val anotherDemo2 = AnotherDemo(2)
// anotherDemo2: AnotherDemo = AnotherDemo(2)
scala> anotherDemo1.getClass
// res6: Class[_ <: AnotherDemo] = class AnotherDemo
scala> anotherDemo2.getClass
// res7: Class[_ <: AnotherDemo] = class AnotherDemo
scala> AnotherDemo.getClass
// res8: Class[_ <: AnotherDemo.type] = class AnotherDemo$
Also, In Scala your class names should start with Capital Letter. This enables you to easily distinguish them from instance variable which should start with small letters. This helps you in avoiding confusion.
Now, it is supposed to be a: String and not a: string.
scala> case class Test(
| a: String,
| b: String,
| c: Int,
| d: Int
| )
// defined class Test
Now, when you write,
scala> var temp = List(Test("lol","lel",1,2))
// temp: List[Test] = List(Test(lol,lel,1,2))
It is actually equivalent to,
var temp = List.apply(Test.apply("lol","lel",1,2))
Or,
val test1 = Test.apply("lol","lel",1,2)
var temp = List.apply(test1)
The Test in Test.apply is not your class Test but the companion object Test. And calling Test.apply returns an instance of class Test which is being passed to List.apply to finally get a List of type List[Test] containing this instance of Test.
But when you write this,
scala> var total = List(Test)
// total: List[Test.type] = List(Test)
You are creating a List of type List[Test.type] containing that companion object of Test.
Focus on total: List[Test.type] part... this means that total is a variable of type List[Test.type] which means that it will want to point to a value/instance of type List[Test.type], and will refuse to point to anything else.
Now... you are trying to do this,
total = total ::: temp
Which is equivalent to,
val x = total ::: temp
total = x
which is actually,
val x = temp.:::(total)
total = x
Now look at this val x = total ::: temp,
scala> val x = total ::: temp
// x: List[Serializable] = List(Test, Test(lol,lel,1,2))
You see... this x is of type List[Serializable]. So when you try total = x, you will get following error,
scala> total = x
// <console>:13: error: type mismatch;
// found : List[Serializable]
// required: List[Test.type]
// total = x
// ^
Which means that total required a List[Test.type] but you are giving it a List[Serializable].
You are looking for total = List.empty[test] rather than List(test).
The former creates an empty list of type List[test], the latter is a one-element list of type List[test.type] (test.type is not the same as test - it is its own object, representing the type of instances of test).
Also, do not use var. They are evil, and not really needed in scala in 99% of uses-cases. Just pretend that keyword does not exist at all, until you get enough of a grip at the language to be able to confidently distinguish the other 1%.
When you do this:
var total = List(test)
You are not initializing the object test, that's why the type of the list is Test.type, you are only creating a list of a template for an object.
When you do this instead:
var temp = List(test("lol","lel",1,2))
Yo have the object instantiated from a template (a class, in this case, Test) so the type of temp is List[Temp].
So, if you do something like:
val template = Test
Then the type of t is Test.type
And you can instantiate an object Test from template like this:
val instantiated = template("lol","lel",1,2)
As you see in your example, the total variable is just a list of templates from where you can instantiate objects while the temp variable is a list of objects of type Test.
To create an empty list of objects of type Test you just have to do:
val t: List[Test] = List.empty
Then you can add any object (of type Test) to this list
Based on your description ('I want to have a running list where elements will be conditionally added in a loop'), my understanding is that you are getting Test objects from some source and want to put them in a list but only if they meet certain criteria. We can express this requirement as a method. For convenience, we'll put the method in the Test companion object. Companion objects are a place to put things that should be available without having to instantiate any objects.
case class Test(a: String, b: String, c: Int, d: Int)
object Test {
/**
Returns a list of `Test` objects that pass the given criteria.
#param tests some source of tests that we can loop over one at a
time.
#param condition checks whether a `Test` object should go into our
output list.
*/
def runningList(
tests: Iterable[Test])(condition: Test => Boolean): List[Test] =
tests.filter(condition).toList
}
You can use it like (e.g.):
Test.runningList(testsSource) { test => test.c > 0 && test.d < 100 }
As you can see here, I've used a few Scala features, like iterables and their list conversion method, multi-parameter-list methods, first-class functions, function-as-last-argument DSL, and so on. If you have more questions on these topics I'd recommend a Scala tutorial.

Scala recursive val behaviour

What do you think prints out?
val foo: String = "foo" + foo
println(foo)
val foo2: Int = 3 + foo2
println(foo2)
Answer:
foonull
3
Why? Is there a part in specification that describes/explains this?
EDIT: To clarify my astonishment - I do realize that foo is undefined at val foo: String = "foo" + foo and that's why it has a default value null (zero for integers). But this doesn't seem very "clean", and I see opinions here that agree with me. I was hoping that compiler would stop me from doing something like that. It does make sense in some particular cases, such as when defining Streams which are lazy by nature, but for strings and integers I would expect either stopping me due to reassignment to val or telling me that I'm trying to use an undefined value, just like as if I wrote val foo = whatever (given that whatever was never defined).
To further complicate things, #dk14 points out that this behaviour is only present for values represented as fields and doesn't happen within blocks, e.g.
val bar: String = {
val foo: String = "foo" + foo // error: forward reference extends...
"bar"
}
Yes, see the SLS Section 4.2.
foo is a String which is a reference type. It has a default value of null. foo2 is an Int which has a default value of 0.
In both cases, you are referring to a val which has not been initialized, so the default value is used.
In both cases foo resp. foo2 have their default values according to the JVM specification. That's null for a reference type and 0 for an int or Int - as Scala spells it.
Scala's Int is backed by a primitive type (int) underneath, and its default value (before initialization) is 0.
On the other hand, String is an Object which is indeed null when not initialized.
Unfortunately, scala is not as safe as let's say Haskell because of compromises with Java's OOP model ("Object-oriented meets Functional"). There is a safe subset of Scala called Scalazzi and some of sbt/scalac-plugins can give you more warnings/errors:
https://github.com/puffnfresh/wartremover (doesn't check for the case you've found though)
Returning back to your case, this happens only for values represented as fields and doesn't happen when you're inside a function/method/block:
scala> val foo2: Int = 3 + foo2
foo2: Int = 3
scala> {val foo2: Int = 3 + foo2 }
<console>:14: error: forward reference extends over definition of value foo2
{val foo2: Int = 3 + foo2 }
^
scala> def method = {val a: Int = 3 + a}
<console>:12: error: forward reference extends over definition of value a
def method = {val a: Int = 3 + a}
The reason of this situation is integration with Java as val compiles to the final field in JVM, so Scala saves all initialization specifics of JVM classes (I believe it's part of JSR-133: Java Memory Model). Here is the more complicated example that explains this behavior:
scala> object Z{ val a = b; val b = 5}
<console>:12: warning: Reference to uninitialized value b
object Z{ val a = b; val b = 5}
^
defined object Z
scala> Z.a
res12: Int = 0
So, here you can see the warning that you didn't see in the first place.

Nulls in Scala ...why is this possible?

I was coding in Scala and doing some quick refactoring in Intellij, when I stumbled upon the following piece of weirdness...
package misc
/**
* Created by abimbola on 05/10/15.
*/
object WTF extends App {
val name: String = name
println(s"Value is: $name")
}
I then noticed that the compiler didn't complain, so I decided to attempt to run this and I got a very interesting output
Value is: null
Process finished with exit code 0
Can anyone tell me why this works?
EDIT:
First problem, the value name is assigned a reference to itself even though it does not exist yet; why exactly does the Scala compiler not explode with errors???
Why is the value of the assignment null?
1.) Why does the compiler not explode
Here is a reduced example. This compiles because through given type a default value can be inferred:
class Example { val x: Int = x }
scalac Example.scala
Example.scala:1: warning: value x in class Example does nothing other than call itself recursively
class Example { val x: Int = x }
This does not compile because no default value can be inferred:
class ExampleDoesNotCompile { def x = x }
scalac ExampleDoesNotCompile.scala
ExampleDoesNotCompile.scala:1: error: recursive method x needs result type
class ExampleDoesNotCompile { def x = x }
1.1 What happens here
My interpretation. So beware: The uniform access principle kicks in.
The assignment to the val x calls the accessor x() which returns the unitialized value of x.
So x is set to the default value.
class Example { val x: Int = x }
^
[[syntax trees at end of cleanup]] // Example.scala
package <empty> {
class Example extends Object {
private[this] val x: Int = _;
<stable> <accessor> def x(): Int = Example.this.x;
def <init>(): Example = {
Example.super.<init>();
Example.this.x = Example.this.x();
()
}
}
} ^
2.) Why the value is null
The default values are determined by the environment Scala is compiled to.
In the example you have given it looks like you run on the JVM. The default value for Object here is null.
So when you do not provide a value the default value is used as a fallback.
Default values JVM:
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'
boolean false
Object null // String are objects.
Also the default value is a valid value for given type:
Here is an example in the REPL:
scala> val x : Int = 0
x: Int = 0
scala> val x : Int = null
<console>:10: error: an expression of type Null is ineligible for implicit conversion
val x : Int = null
^
scala> val x : String = null
x: String = null
why exactly does the Scala compiler not explode with errors?
Because this problem can't be solved in the general case. Do you know the halting problem? The halting problem says that it is not possible to write an algorithm that finds out if a program ever halts. Since the problem of finding out if a recursive definition would result in a null assignment can be reduced to the halting problem, it is also not possible to solve it.
Well, now it is quite easy to forbid recursive definitions at all, this is for example done for values that are no class values:
scala> def f = { val k: String = k+"abc" }
<console>:11: error: forward reference extends over definition of value k
def f = { val k: String = k+"abc" }
^
For class values this feature is not forbidden for a few reasons:
Their scope is not limited
The JVM initializes them with a default value (which is null for reference types).
Recursive values are useful
Your use case is trivial, as is this:
scala> val k: String = k+"abc"
k: String = nullabc
But what about this:
scala> object X { val x: Int = Y.y+1 }; object Y { val y: Int = X.x+1 }
defined object X
defined object Y
scala> X.x
res2: Int = 2
scala> Y.y
res3: Int = 1
scala> object X { val x: Int = Y.y+1 }; object Y { val y: Int = X.x+1 }
defined object X
defined object Y
scala> Y.y
res4: Int = 2
scala> X.x
res5: Int = 1
Or this:
scala> val f: Stream[BigInt] = 1 #:: 1 #:: f.zip(f.tail).map { case (a,b) => a+b }
f: Stream[BigInt] = Stream(1, ?)
scala> f.take(10).toList
res7: List[BigInt] = List(1, 1, 2, 3, 5, 8, 13, 21, 34, 55)
As you can see it is quite easy to write programs where it is not obvious anymore to which value they will result. And since the halting problem is not solvable we can not let the compiler do the work for us in non trivial cases.
This also means that trivial cases, as the one shown in your question, could be hardcoded in the compiler. But since there can't exist a algorithm that can detect all possible trivial cases, all cases that are ever found need to be hardcoded in the compiler (not to mention that a definition of a trivial case does not exist). Therefore it wouldn't be wise to even start hardcoding some of these cases. It would ultimately result in a slower compiler and a compiler that is more difficult to maintain.
One could argue that for an use case that burns every second user it would be wise to at least hardcode such an extreme scenario. On the other hand, some people just need to be burned in order to learn something new. ;)
I think #Andreas' answer already has the necessary info. I'll just try to provide additional explanation:
When you write val name: String = name at the class level, this does a few different things at the same time:
create the field name
create the getter name()
create code for the assignment name = name, which becomes part of the primary constructor
This is what's made explicit by Andreas' 1.1
package <empty> {
class Example extends Object {
private[this] val x: Int = _;
<stable> <accessor> def x(): Int = Example.this.x;
def <init>(): Example = {
Example.super.<init>();
Example.this.x = Example.this.x();
()
}
}
}
The syntax is not Scala, it is (as suggested by [[syntax trees at end of cleanup]]) a textual representation of what the compiler will later convert into bytecode. Some unfamiliar syntax aside, we can interpret this, like the JVM would:
the JVM creates an object. At this point, all fields have default values. val x: Int = _; is like int x; in Java, i.e. the JVM's default value is used, which is 0 for I (i.e. int in Java, or Int in Scala)
the constructor is called for the object
(the super constructor is called)
the constructor calls x()
x() returns x, which is 0
x is assigned 0
the constructor returns
as you can see, after the initial parsing step, there is nothing in the syntax tree that seems immediately wrong, even though the original source code looks wrong. I wouldn't say that this is the behavior I expect, so I would imagine one of three things:
Either, the Scala devs saw it as too intricate to recognize and forbid
or, it's a regression and simply wasn't found as a bug
or, it's a "feature" and there is legitimate need for this behavior
(ordering reflects my opinion of likeliness, in decreasing order)

Scala: replace method at runtime

Let's say I have a class
class Original {
def originalMethod = 1
}
Now, let's say I have an instance of it
val instance = new Original
Is it now possible to do something to instance at runtime to replace the originalMethod with a different method? (granted the signature stays the same)
For example, now, when calling instance.originalMethod the following code will be called println("test"); 1
EDIT
I can't call new Original. I just have an existing instance of it, which I have to modify.
EDIT 2
(#Aleksey Izmailov answer) This is a nice solution, but isn't exactly what I'm looking for. I'm thinking more in terms of testing - writing a class "normally", without specifying functions as variables rather than methods
PS. I stumbled on this question when trying to mimic a Mockito spy
Seems like you have to revert to mutation since you can't have new instances and behavior has to change. Here is perhaps the simplest option (REPL):
Store a function as a mutable field:
scala> class Original {
| var originalMethod = () => 1
| }
defined class Original
scala> val obj = new Original
obj: Original = Original#66ac5762
It's a function that takes nothing, and you need to call apply or () on it to get result.
scala> obj.originalMethod
res0: () => Int = <function0>
scala> obj.originalMethod()
res1: Int = 1 ^
Replace it with a new function:
scala> obj.originalMethod = () => 2
obj.originalMethod: () => Int = <function0>
Now you are getting new behaviour:
scala> obj.originalMethod()
res2: Int = 2
Interestingly enough you can't have default implementation with a generic version of this class because there is no default value you could use unless you change it to Unit or partial function.
Here is a generic version of it:
scala> class Original[T] {
| var originalMethod: () => T = null
| }
defined class Original
scala> val genImpl = new Original[Int] { originalMethod = () => 111 }
genImpl: Original[Int] = $anon$1#6b04acb2
scala> genImpl.originalMethod()
res8: Int = 111
scala> genImpl.originalMethod = () => 222
genImpl.originalMethod: () => Int = <function0>
scala> genImpl.originalMethod()
res9: Int = 222
This isn't possible on the JVM — in either Java or Scala — not in the way that you're asking for.
See e.g. In Java, given an object, is it possible to override one of the methods?
Being in Scala instead of Java doesn't gain you additional leverage, since the fundamentals of how classes and methods work in Scala are the same as Java's. (This was done for both performance and interop reasons.)

Getting a null with a val depending on abstract def in a trait [duplicate]

This question already has answers here:
Scala - initialization order of vals
(3 answers)
Closed 7 years ago.
I'm seeing some initialization weirdness when mixing val's and def's in my trait. The situation can be summarized with the following example.
I have a trait which provides an abstract field, let's call it fruit, which should be implemented in child classes. It also uses that field in a val:
scala> class FruitTreeDescriptor(fruit: String) {
| def describe = s"This tree has loads of ${fruit}s"
| }
defined class FruitTreeDescriptor
scala> trait FruitTree {
| def fruit: String
| val descriptor = new FruitTreeDescriptor(fruit)
| }
defined trait FruitTree
When overriding fruit with a def, things work as expected:
scala> object AppleTree extends FruitTree {
| def fruit = "apple"
| }
defined object AppleTree
scala> AppleTree.descriptor.describe
res1: String = This tree has loads of apples
However, if I override fruit using a val...
scala> object BananaTree extends FruitTree {
| val fruit = "banana"
| }
defined object BananaTree
scala> BananaTree.descriptor.describe
res2: String = This tree has loads of nulls
What's going on here?
In simple terms, at the point you're calling:
val descriptor = new FruitTreeDescriptor(fruit)
the constructor for BananaTree has not been given the chance to run yet. This means the value of fruit is still null, even though it's a val.
This is a subcase of the well-known quirk of the non-declarative initialization of vals, which can be illustrated with a simpler example:
class A {
val x = a
val a = "String"
}
scala> new A().x
res1: String = null
(Although thankfully, in this particular case, the compiler will detect something being afoot and will present a warning.)
To avoid the problem, declare fruit as a lazy val, which will force evaluation.
The problem is the initialization order. val fruit = ... is being initialized after val descriptor = ..., so at the point when descriptor is being initialized, fruit is still null. You can fix this by making fruit a lazy val, because then it will be initialized on first access.
Your descriptor field initializes earlier than fruit field as trait intializes earlier than class, that extends it. null is a field's value before initialization - that's why you get it. In def case it's just a method call instead of accessing some field, so everything is fine (as method's code may be called several times - no initialization here). See, http://docs.scala-lang.org/tutorials/FAQ/initialization-order.html
Why def is so different? That's because def may be called several times, but val - only once (so its first and only one call is actually initialization of the fileld).
Typical solution to such problem - using lazy val instead, it will intialize when you really need it. One more solution is early intializers.
Another, simpler example of what's going on:
scala> class A {val a = b; val b = 5}
<console>:7: warning: Reference to uninitialized value b
class A {val a = b; val b = 5}
^
defined class A
scala> (new A).a
res2: Int = 0 //null
Talking more generally, theoretically scala could analize the dependency graph between fields (which field needs other field) and start initialization from final nodes. But in practice every module is compiled separately and compiler might not even know those dependencies (it might be even Java, which calls Scala, which calls Java), so it's just do sequential initialization.
So, because of that, it couldn't even detect simple loops:
scala> class A {val a: Int = b; val b: Int = a}
<console>:7: warning: Reference to uninitialized value b
class A {val a: Int = b; val b: Int = a}
^
defined class A
scala> (new A).a
res4: Int = 0
scala> class A {lazy val a: Int = b; lazy val b: Int = a}
defined class A
scala> (new A).a
java.lang.StackOverflowError
Actually, such loop (inside one module) can be theoretically detected in separate build, but it won't help much as it's pretty obvious.