Scala - How is a variable of type Any stored in memory? - scala

How is it possible to create variable of type Any?
And why does isInstanceOf[Int] print true?
I declared x to be Any, not Int.
How does it work? What is happening behind the scenes?
val x = 4: Any // OK
x.isInstanceOf[Int] // true
x.isInstanceOf[String] // false
[EDIT] Maybe to rephrase my question:
How does val x = 4: Any look like in memory?
And once it is stored in memory as Any type, how can I later say that this particular blob of bytes is Int, but not say String?
Does it come along with some kind of information what was the "original" type? Here for example if I typed 4 AND LATER said this is Any type, would it store this original type of 4 as an Int?

Scala language is defined to support the notion of inheritance polymorphism. In other words, if there is some type T which inherits from type U, then any value of type T can be assigned to a variable of type U:
class T extends U
val x: U = new T // compiles
Same thing with Any and Int: in Scala, Int inherits from Any, therefore it is possible to store an integer in an Any variable:
val x: Any = 4 // essentially the same as your example
Also, all of the runtimes Scala runs on know what type of value is actually stored in a variable, regardless of the static type of this variable. This is important for many features of the language, in particular, virtual method overrides, but it also allows you to do manual checks and downcasts, which is what your code does (the checks). In other words, the isInstanceOf method checks the runtime type of a value stored in a variable, not the static type known at the compile time (which would be quite pointless).

Related

Is int type in Dart a value type or reference type?

The int type in Dart has default value of null. null is an object of type Null class. (as per Dart documentation). Also, in Dart, int derives from class Object.
Hence,
int i = 10;
print(i.runtimeType is Object); // returns true
This makes me believe that int is not a value type like in other languages (such as C#) but a reference type.
If I am correct, then-
int i = 10;
means i is a reference variable holding the reference to an int object 10.
Is this correct? If not, I would appreciate if a link to the description in the documentation is shared.
Till now, I've been unable to find any proper explanation and hence have come to this conclusion myself.
Thanks.
Yes, Dart's int type is a "reference type".
Dart does not have value types at all, all values are instances of a class, including integers. (At least technically, function values makes their classes very hard to see.)
Integers are immutable and pretends to be canonicalized.
If a and b are int values and a == b, then identical(a, b) is guaranteed to be true, so a and b looks like they are the same object, but it's unspecified whether that's because they really are the same object, or because identical just cheats and does == for integers.
That means that you can largely treat int as a "value type". Whether it is copied on assignment or parameter passing, or you are passing a reference to the same object, is impossible to tell apart. The language ensures that, because it allows the implementations to do whatever is more efficient.
In practice, some integers are unboxed inside functions, some integers are stored as a value in the reference itself, and some are real objects.
(That's also one of the reasons you can't use an Expando with an int).
(In the current Dart language, all types annotations are nullable, meaning that you can assign null to int x;. With the upcoming Null Safety feature, that changes. Types will only be nullable if you write them as such, so int x = 1; would not accept a null value, but int? x; would. And null is an object too, the only instance of the class Null.)
int is a value type in the sense that if you pass int value into a function and change the value of a parameter inside function, it won't affect outer scope.
void add(int inner) {
inner += 1;
}
int outer = 0;
add(outer);
print(outer); // 0, unchanged
But int is still a class even though its name starts from lowercase letter. There was a huge discussion about its naming and lots of people consider it an inconsistency.
Yes int is a class (it even extends num) and therefor has common methods to use on. But one the other side it is different than "normal" classes since you don't have to use a constructor like
int i = int(3);
See int's class documenation https://api.dart.dev/stable/2.8.4/dart-core/int-class.html
Everything in Dart is an object, int, double or num may look like keywords but they are built-in abstract classes. Since they are abstract classes which means they can not be instantiated, they do not start with an uppercase letter.
try this line,
print('2 is instance of "int" class :\t${ 2 is int}');
this will result in true.
And regarding your concern about 'null' :
In Dart, like JavaScript and Python, everything that a variable can hold is an object including null. Every object including null is an instance of some class and all these classes inherit from Object class.
your can refer this link for more info.
Hope this helps.

Add objects from case class in Scala

So, I am new to programming and this might be a very rookie question.
I need to add elements to an object. How is this done?
scala> case class test (
a: String,
b: String,
c: Int,
d: Int
)
var teamData_Temp = test(lol, lel,1, 2)
var teamData_All = teamData_Temp
Then let's say that teamData_Temp becomes teamData_temp = test(kok,kek,3,4) at some point in the script
How do I produce teamData_All = (test(lol,lel,1,2),test(kok,kek,3,4)) ???
Scala is a statically typed language. This means that although variables declared with var can be replaced with a new value, the type of that variable cannot change over the lifetime of the program. The type of teamData_All in your script is test while the type of teamData_All that you are trying to change it to is Tuple2[test, test] (or equivalently (test, test)). These are incompatible types.
If you want to have teamData_All be growable, you have to specify that sort of behavior upfront when declaring the variable, e.g. by making it a list of type List[test]. Then you could have one line set teamData_All = List(test(lol,lel,1,2)) and then have another line set teamData_All = List(test(lol,lel,1,2),test(kok,kek,3,4)).
The reason why this is necessary for a statically typed language is because if you make references to teamData_All in multiple places in your code, there is no way for the compiler to statically, i.e. before running your code, know what the type of teamData_All is at a given point, since you might have changed its type. This makes it impossible for the compiler to make its usual guarantees (e.g. making sure you're only calling methods on things that actually have that method defined).

why scala value class#toString contains case class info?

value classes can be used to achieve type safety without the overhead of unboxing.
I had the impression that in runtime such types/classes would "not exist", being seen as simple types (for instance, a value class case class X(i: Int) extends AnyVal would be a simple Int on runtime).
But if you do call a .toString method on a value class instance it would print something like:
scala> val myValueClass = X(3)
myValueClass: X = 3
scala> myValueClass.toString
res5: String = X(3)
so I guess the compiler includes some information after all?
Not really. The compiler creates a static method (in Scala this corresponds to the class's companion object) which is called with your int value as a parameter in order to simulate calling a method on your value class-typed object.
Your value class itself only exists in the source code. In compiled bytecode an actual primitive int is used and static methods are called rather than new object instances with real method calls. You can read more about this mechanism here.
Value classes are designed so that adding or removing extends AnyVal (if legal) shouldn't change the results of calculations (except even non-case value classes have equals and hashCode defined automatically like case classes). This requires that in some circumstances they survive, e.g.
def toString(x: Any) = x.toString
toString(myValueClass)
but the situation in your question isn't one of them.
http://docs.scala-lang.org/sips/completed/value-classes.html#expansion-of-value-classes explains more precisely how value classes are implemented and is useful to see in what cases they survive, though some details may have changed since.

what does A#B mean in scala

I am trying to understand the following piece of code. but I don't know what the R#X mean. could someone help me?
// define the abstract types and bounds
trait Recurse {
type Next <: Recurse
// this is the recursive function definition
type X[R <: Recurse] <: Int
}
// implementation
trait RecurseA extends Recurse {
type Next = RecurseA
// this is the implementation
type X[R <: Recurse] = R#X[R#Next]
}
object Recurse {
// infinite loop
type C = RecurseA#X[RecurseA]
}
You may gain type from existing instance of a class:
class C {
type someType = Int
}
val c = new C
type t = c.someType
Or may address to the type directly without instantiating an object: C#someType This form is very usefull for type expressions where you have no space to create intermediate variables.
Adding some clarifications as it was suggested in comments.
Disclaimer: I have only partial understanding of how Scala's type system works. I'd tried to read documentation several times, but was able to extract only patchy knowledges from it. But I have rich experience in scala and may predict compilers behavior on individual cases well.
# called type projection and type projection compliments normal hierarchical type access via . In every type expression scala implicitly uses both.
scala reference gives examples of such invisible conversions:
t ə.type#t
Int scala.type#Int
scala.Int scala.type#Int
data.maintable.Node data.maintable.type#Node
As use see, every trivial usage of type projection actually works on type (that is return with .type) not on an object. The main practical difference (I'm bad with definitions) is that object type is something ephemeral as object itself is. Its type may be changed in appropriate circumstances such as inheritance of an abstract class type. In contrast type's type (the definition of the type projection) is as stable as sun. Types (don't mix them with classes) in scala are not first-class citizens and can not be overridden further.
There are different places suitable for putting type expression into. There are also some places where only stable types are allowed. So basically type projection is more constant for terms of type.

scala: why does underscore (_) initialization work for fields but not method variables?

this works:
scala> class foo[T] {
| var t: T = _
| }
defined class foo
but this doesn't:
scala> def foo[T] = {
| var t: T = _
| }
<console>:5: error: local variables must be initialized
var t: T = _
why?
(one can use:
var t: T = null.asInstanceOf[T]
)
There is a mailing list thread where Martin answered:
It corresponds to the JVM. You can omit a field initialization but not a local variable initialization. Omitting local variable initializations means that the compiler has to be able to synthesize a default value for every type. That's not so easy in the face of type parameters, specialization, and so on.
When pressed about how there is or should be any distinction between fields and locals in the matter of Scala synthesizing default values, he went on to say:
In terms of bytecodes there IS a clear difference. The JVM will initialize object fields by default and require that local variables are initialized explicitly. […] I am not sure whether we should break a useful principle of Java (locals have to be initialized before being used), or whether we should rather go the full length and introduce flow-based initialization checking as in Java. That would be the better solution, IMO, but would require significant work in terms of spec and implementation. Faced with these choices my natural instinct is to do nothing for now :-)
So if I understand correctly, the Scala compiler does not actually synthesize default values for object fields, it produces bytecode that leaves the JVM to handle this.
According to SI-4437 there was agreement from Martin on actually endorsing the null.asInstanceOf[T] pattern in the language spec, seemingly for lack of being able to feasibly support a better alternative within existing constraints.
This is defined in section 4.2 of the Scala Language Specification (my italics)
A variable definition var x: T = _ can appear only as a member of a template. It
introduces a mutable field with type T and a default initial value
This, of course, does not answer the why this should be so!
Here is at least one use case that I just uncovered. When then superclass initializes member variables via reflection it can actually initialize a subclasses member variables. However, if a subclass also initializes the member variable with a value, then this will have the effect of overwriting the value that the superclass gave it. This can be avoided by initializing the subclasses member variable with the underscore. This is why the language spec talks about giving the variable a getter function that returns the current value a little further down from the quoted sentence in oxbow_lake's sentence.