Scala var type usage results in type mismatch - scala

I thought that Scala var type is cool, helps to avoid tons of some technical code and makes it possible to concentrate on functionality. However, I now face something really strange. When I compile my program, I get an error message from sbt:
type mismatch;
found: java.sql.Connection
required: String
this.conn = DriverManager.getConnection(
^
Please, pay attention that the compiler points to conn property of the class, and this property is defined in the class like so:
class Db{
private var conn = ""
....
}
So, why does compiler care about types matching, if it is Scala and if I'm using var data type?

var is not a data type. It is a keyword for declaring and defining a mutable variable. The type is not dynamic---it is still inferred at compile-time. In this case conn is inferred to be a String, and it is completely identical to writing
private var conn: String = ""
The whole point of Scala's type system is to disallow passing incompatible types around. It's failing because, obviously, you cannot assign an SQL connection to a variable of type String. Type inference does not allow you to ignore the types of objects, it just lets the compiler figure it out where possible.

var is not a data type, it's one keyword used to define variables in Scala. The other one is val. Whether you use var or val only affects whether the variable you define can be re-assigned to (var) or is read-only (val). It does not affect the type of the variable in anyway.
Regardless of whether you use var or val, the type of a variable is either specified explicitly (by writing : theType after the variable name) or inferred implicitly from the value you assign it to.
In your example, you did not explicitly provide a type, so the inferred type was String as that is the type of conn.

Related

Dart/Flutter : The meaning of "whether some code is annotated or inferred is orthogonal to whether it is dynamic or some other type"

https://dart.dev/guides/language/effective-dart/design#types
If the code is type annotated, the type was explicitly written in the
code.
If the code is inferred, no type annotation was written, and Dart
successfully figured out the type on its own. Inference can fail, in
which case the guidelines don’t consider that inferred.
If the code is dynamic, then its static type is the special dynamic
type. Code can be explicitly annotated dynamic or it can be inferred.
In other words, whether some code is annotated or inferred is
orthogonal to whether it is dynamic or some other type.
The above explanation is extremely abstract and I'm not sure exactly what this means.
Especially the last sentence, does it mean that "it may be inferred as another type even though it is type-annotated as'dyanmic'"?
But maybe I feel it's not right.
Because I remember being told by the IDE during development that something like "because it's a dynamic type, you can't access that member."
If not, I would like a more specific explanation of what it means after all.
It would be helpful if you could get some clues.
Basically, a variable can be type annotated:
int x = 1;
also, it can be inferred:
var x = 1; // dart knows x is an integer because you assigned 1 to it.
A variable can be dynamic, meaning it's type can change.
That's what the three first sentences mean, the last sentence is saying that a dynamic variable can be either inferred or annotated:
dynamic someFunction() {
return 1;
}
dynamic x = 'aaa'; // annotated
var y = someFunction(); // inferred
So weather a variable is annotated or inferred has nothing to do with weather it is dynamic or not.

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

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).

var declaration with type vs without

What is the difference between this
var a = ClassA()
and this
var a: ClassA = ClassA()
Why do one vs the other?
I'm not a Swift developer but I'm fairly certain that it operates in the same way as languages like C# in this regard.
In the first case, the type of the variable is inferred from the type of the expression used to initialise it. Your a variable is thus of type ClassA and can thus refer to any object that is that type or is derived from it. In the second case, you are specifying that the variable is type ClassA explicitly rather than allowing it to be inferred.
In that second case, the annotation is redundant because the specified type is the same as that which would be inferred anyway. If those types were different though, then it would be worthwhile, e.g.
var a: BaseType = DerivedType()
In this case, the variable is being initialised with an object that is one type but the variable is specified to be a type that is more general.
If you are declaring a variable without initialising it then you need an annotation too, because there is no initialising expression from which to infer the variable's type.

Scala: Why is it necessary to assign values to a var/val during declaration

Unless I've been doing it wrong. It doesn't seem like we can do things like:
var x;
x = 1;
in Scala, but rather you have to declare and assign a value to it. Are there any reasons for why this is the case?
The obvious reason is to help not leave variables uninitialized.
Note that in your declaration without initialization, you will also need to specify the type.
var x: Type;
gives the following error:
only classes can have declared but undefined members (Note that variables need to be initialized to be defined)
Actually only abstract classes can declare members without defining them. You can still get the desired behavior (variables initialized to a default value) as
var x: Type = _
If Type is a reference type, x will be null. This scenario is useful, for example, in case where a factory method completes initialization of an object after object construction.

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.